From 4736d0f27e4123e5d189dcf1a2edc068280dcaeb Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Jul 2026 17:01:33 +0000 Subject: [PATCH 1/3] build(android-llmservice): bump Compose compiler plugin 2.4.0 -> 2.4.10 Patch bump of org.jetbrains.kotlin.plugin.compose; tracks the Kotlin version and stays above AGP's bundled Kotlin floor. No other change. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MeheJtyQwUzJGLcYpyWURD --- android-llmservice/README.md | 2 +- android-llmservice/settings.gradle.kts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android-llmservice/README.md b/android-llmservice/README.md index d0338585e..e511e36d4 100644 --- a/android-llmservice/README.md +++ b/android-llmservice/README.md @@ -199,7 +199,7 @@ gradle -p android-llmservice connectedDebugAndroidTest -PjllamaVersion="$VERSION ``` android-llmservice/ -├── settings.gradle.kts # AGP 9.2.1 (built-in Kotlin) + Compose plugin 2.4.0, mavenLocal first +├── settings.gradle.kts # AGP 9.2.1 (built-in Kotlin) + Compose plugin 2.4.10, mavenLocal first ├── gradle.properties ├── requirements.md # spec of record: every feature the app implements today (no unit tests) ├── TODO.md # roadmap: not-yet-built features diff --git a/android-llmservice/settings.gradle.kts b/android-llmservice/settings.gradle.kts index 37ad3a125..8bddfb730 100644 --- a/android-llmservice/settings.gradle.kts +++ b/android-llmservice/settings.gradle.kts @@ -22,11 +22,11 @@ pluginManagement { // AGP 9.0+ has built-in Kotlin support (runtime dependency on Kotlin Gradle plugin // 2.2.10+), so the standalone org.jetbrains.kotlin.android plugin is no longer // applied/needed — see https://developer.android.com/build/migrate-to-built-in-kotlin. - // The Compose compiler plugin (2.4.0) still applies separately and exceeds AGP's + // The Compose compiler plugin (2.4.10) still applies separately and exceeds AGP's // 2.2.10 floor. plugins { id("com.android.application") version "9.2.1" - id("org.jetbrains.kotlin.plugin.compose") version "2.4.0" + id("org.jetbrains.kotlin.plugin.compose") version "2.4.10" } } From d27111c4f8923ee41cc185ab9e09e494971cea2c Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Jul 2026 18:04:06 +0000 Subject: [PATCH 2/3] build(android): bump AGP 9.2.1 -> 9.3.0 (Gradle pin 9.4.1 -> 9.5.0) Bumps com.android.application to 9.3.0 in both the android-llmservice app and the .github/android-consumer-test fixture. AGP 9.3.x requires Gradle >= 9.5.0, so the four gradle-version pins on the AGP-building CI jobs move 9.4.1 -> 9.5.0 (the AAR/lib-only jobs stay on their older Gradle). JDK floor stays 17 (CI runs 21); max API stays 37 (compileSdk 37). The R8 RecordTag regression fix first shipped in 9.2.1 is carried forward by 9.3.0. Docs (README, CLAUDE.md) updated to match. Validated only against Android's official AGP<->Gradle compatibility table; the isMinifyEnabled release/R8 path is validated by CI, which has the Android SDK a local sandbox lacks. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MeheJtyQwUzJGLcYpyWURD --- .../android-consumer-test/settings.gradle.kts | 8 +++---- .github/workflows/publish.yml | 16 +++++++------- CLAUDE.md | 22 +++++++++---------- android-llmservice/README.md | 2 +- android-llmservice/settings.gradle.kts | 11 +++++----- 5 files changed, 30 insertions(+), 29 deletions(-) diff --git a/.github/android-consumer-test/settings.gradle.kts b/.github/android-consumer-test/settings.gradle.kts index f12957771..542f54fac 100644 --- a/.github/android-consumer-test/settings.gradle.kts +++ b/.github/android-consumer-test/settings.gradle.kts @@ -14,13 +14,13 @@ pluginManagement { gradlePluginPortal() } plugins { - // AGP 9.x requires Gradle >= 9.4.1 — see the gradle-version pins on the CI jobs + // AGP 9.3.x requires Gradle >= 9.5.0 — see the gradle-version pins on the CI jobs // that build this fixture in publish.yml (package-android-aar, test-android-emulator). - // 9.2.1 (not 9.2.0) is pinned: it fixes a real R8 regression + // Stay at >= 9.2.1: 9.2.1 (not 9.2.0) first fixed a real R8 regression // (java.lang.ClassNotFoundException on com.android.tools.r8.RecordTag after // upgrading Gradle to 9.x with AGP 9.2.0) that hits this fixture directly since - // buildTypes.release sets isMinifyEnabled = true. - id("com.android.application") version "9.2.1" + // buildTypes.release sets isMinifyEnabled = true; 9.3.0 carries that fix forward. + id("com.android.application") version "9.3.0" } } diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8ea8e2ec4..2b6c89818 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -917,8 +917,8 @@ jobs: distribution: temurin - uses: gradle/actions/setup-gradle@v6 with: - # AGP 9.2.0 (the .github/android-consumer-test fixture) requires Gradle >= 9.4.1. - gradle-version: "9.4.1" + # AGP 9.3.0 (the .github/android-consumer-test fixture) requires Gradle >= 9.5.0. + gradle-version: "9.5.0" - name: Build core jar (byte-identical classes payload for the AAR) run: > mvn -B --no-transfer-progress -pl llama -am -DskipTests -Denforcer.skip=true @@ -1048,8 +1048,8 @@ jobs: distribution: temurin - uses: gradle/actions/setup-gradle@v6 with: - # AGP 9.2.0 (the .github/android-consumer-test fixture) requires Gradle >= 9.4.1. - gradle-version: "9.4.1" + # AGP 9.3.0 (the .github/android-consumer-test fixture) requires Gradle >= 9.5.0. + gradle-version: "9.5.0" - name: Enable KVM group permissions (GitHub-hosted runner) run: | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules @@ -1142,10 +1142,10 @@ jobs: distribution: temurin - uses: gradle/actions/setup-gradle@v6 with: - # AGP 9.2.0 (android-llmservice) requires Gradle >= 9.4.1; also satisfies Kotlin + # AGP 9.3.0 (android-llmservice) requires Gradle >= 9.5.0; also satisfies Kotlin # 2.4's Gradle-plugin floor. The AAR/lib-only jobs stay on an older Gradle since # they build no AGP project. - gradle-version: "9.4.1" + gradle-version: "9.5.0" - name: Build core jar + install llama-kotlin facade to mavenLocal # install (not package) so the app's Gradle build resolves llama-kotlin + # the core POM from mavenLocal. llama-kotlin's core dep is provided-scope, so the @@ -1228,8 +1228,8 @@ jobs: distribution: temurin - uses: gradle/actions/setup-gradle@v6 with: - # AGP 9.2.0 (android-llmservice) requires Gradle >= 9.4.1. - gradle-version: "9.4.1" + # AGP 9.3.0 (android-llmservice) requires Gradle >= 9.5.0. + gradle-version: "9.5.0" - name: Enable KVM group permissions (GitHub-hosted runner) run: | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules diff --git a/CLAUDE.md b/CLAUDE.md index 9d7ee1928..de61a6dbf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1677,20 +1677,20 @@ compiles/loads the API); this one has a UI and is driven end-to-end. The name is domain is the only string that must be globally unique. Structure (mirrors the consumer-test's plumbing): -- **`settings.gradle.kts`** — `rootProject.name = "android-llmservice"`; pins AGP `9.2.1` + the - Compose compiler plugin (`2.4.0`); `mavenLocal()` first so the freshly-built AAR + façade - resolve there in CI (Maven Central for real users). `9.2.1` (not `9.2.0`) fixes a real R8 - regression (`ClassNotFoundException` on `com.android.tools.r8.RecordTag` after upgrading - Gradle to 9.x with AGP 9.2.0) that hits this project directly since `buildTypes.release` - sets `isMinifyEnabled = true`; the `.github/android-consumer-test` fixture is pinned the - same way for the same reason. AGP 9.x requires Gradle >= 9.4.1 and - JDK 17+; CI already runs JDK 21 everywhere (`env.JAVA_VERSION`), so only the `gradle-version` +- **`settings.gradle.kts`** — `rootProject.name = "android-llmservice"`; pins AGP `9.3.0` + the + Compose compiler plugin (`2.4.10`); `mavenLocal()` first so the freshly-built AAR + façade + resolve there in CI (Maven Central for real users). Stay at `>= 9.2.1`: `9.2.1` (not `9.2.0`) + first fixed a real R8 regression (`ClassNotFoundException` on `com.android.tools.r8.RecordTag` + after upgrading Gradle to 9.x with AGP 9.2.0) that hits this project directly since + `buildTypes.release` sets `isMinifyEnabled = true`; `9.3.0` carries that fix forward and the + `.github/android-consumer-test` fixture is pinned the same way. AGP 9.3.x requires Gradle >= 9.5.0 + and JDK 17+; CI already runs JDK 21 everywhere (`env.JAVA_VERSION`), so only the `gradle-version` pin on the jobs that build this project (and the `.github/android-consumer-test` fixture) - needed bumping. AGP 9.0+ has **built-in Kotlin support** (a runtime dependency on Kotlin - Gradle plugin 2.2.10+), so the standalone `org.jetbrains.kotlin.android` plugin is no longer + needed bumping (9.4.1 → 9.5.0). AGP 9.0+ has **built-in Kotlin support** (a runtime dependency on + Kotlin Gradle plugin 2.2.10+), so the standalone `org.jetbrains.kotlin.android` plugin is no longer applied — applying it now fails the build with "no longer required for Kotlin support since AGP 9.0" (`app/build.gradle.kts` line 7). The Compose compiler plugin still applies - separately and its 2.4.0 pin exceeds AGP's 2.2.10 floor, so no other version changed. + separately and its 2.4.10 pin exceeds AGP's 2.2.10 floor, so no other version changed. - **`app/build.gradle.kts`** — `namespace`/`applicationId` `net.ladenthin.android.llmservice`, `minSdk 28` (AAR floor), `compileSdk 37` (raised from 35 — Compose/lifecycle/activity AAR metadata now requires it), `targetSdk 35`, Jetpack Compose, `androidx.appcompat` (only for diff --git a/android-llmservice/README.md b/android-llmservice/README.md index e511e36d4..fc926623e 100644 --- a/android-llmservice/README.md +++ b/android-llmservice/README.md @@ -199,7 +199,7 @@ gradle -p android-llmservice connectedDebugAndroidTest -PjllamaVersion="$VERSION ``` android-llmservice/ -├── settings.gradle.kts # AGP 9.2.1 (built-in Kotlin) + Compose plugin 2.4.10, mavenLocal first +├── settings.gradle.kts # AGP 9.3.0 (built-in Kotlin) + Compose plugin 2.4.10, mavenLocal first ├── gradle.properties ├── requirements.md # spec of record: every feature the app implements today (no unit tests) ├── TODO.md # roadmap: not-yet-built features diff --git a/android-llmservice/settings.gradle.kts b/android-llmservice/settings.gradle.kts index 8bddfb730..bae0aad35 100644 --- a/android-llmservice/settings.gradle.kts +++ b/android-llmservice/settings.gradle.kts @@ -14,18 +14,19 @@ pluginManagement { gradlePluginPortal() } // Versions pinned here (KISS: no version catalog). AGP matches the consumer-test - // fixture. AGP 9.x requires Gradle >= 9.4.1 — see the gradle-version pins on the CI - // jobs that build this project in publish.yml. 9.2.1 (not 9.2.0) is pinned: it fixes - // a real R8 regression (java.lang.ClassNotFoundException on + // fixture. AGP 9.3.x requires Gradle >= 9.5.0 — see the gradle-version pins on the CI + // jobs that build this project in publish.yml. Stay at >= 9.2.1: 9.2.1 (not 9.2.0) + // first fixed a real R8 regression (java.lang.ClassNotFoundException on // com.android.tools.r8.RecordTag after upgrading Gradle to 9.x with AGP 9.2.0) that - // hits this project directly since buildTypes.release sets isMinifyEnabled = true. + // hits this project directly since buildTypes.release sets isMinifyEnabled = true; + // 9.3.0 carries that fix forward. // AGP 9.0+ has built-in Kotlin support (runtime dependency on Kotlin Gradle plugin // 2.2.10+), so the standalone org.jetbrains.kotlin.android plugin is no longer // applied/needed — see https://developer.android.com/build/migrate-to-built-in-kotlin. // The Compose compiler plugin (2.4.10) still applies separately and exceeds AGP's // 2.2.10 floor. plugins { - id("com.android.application") version "9.2.1" + id("com.android.application") version "9.3.0" id("org.jetbrains.kotlin.plugin.compose") version "2.4.10" } } From 180d1c080ee4d081d11d86427b769b2e3d15b462 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Jul 2026 19:02:19 +0000 Subject: [PATCH 3/3] Upgrade llama.cpp from b10107 to b10154 Bumps the pinned llama.cpp release across the four canonical files (CMakeLists.txt GIT_TAG + LLAMA_TAG, README badge, CLAUDE.md, and the LlamaCppVersion.LLAMA_CPP_VERSION Java constant) and refreshes patches/. Patch refresh (b10154 added upstream MCP-server support): - 0001: one common/arg.h hunk drifted (b10154 inserted common_print_available_devices() beside common_params_parse); the other 36 files applied unchanged. Regenerated against b10154. - 0007: reworked. b10154 moved the resumable-streaming routes (/v1/stream/:conv_id -> /v1/stream) into the middle of the route/CORS/tools block and coupled tools/CORS to a new server_mcp mcp_mgr lifecycle (2-arg tools.setup), so the old contiguous 'route-table + CORS-proxy + tools' extraction is no longer possible. The shared helper llama_server_register_common_routes() is narrowed to the pure core route table (health..slots); llama_server() keeps the streaming/GCP/CORS/MCP/tools blocks inline, byte-identical to upstream b10154. llama_server_attach() registers the route table + non-router streaming on the new /v1/stream paths + GCP compat + 403 stubs for the experimental /cors-proxy + /tools endpoints it does not wire. - 0002/0003/0006/0008 apply unchanged. No project source change needed. Verified in-sandbox: all 6 patches apply clean in order against a fresh b10154 checkout; cmake configure passes (fail-loud patch applier + OuteTTS generator anchors hold); full jllama shared-library build compiles and links at -O3; all 485 C++ unit tests pass. Appends the b10107-b10154 row to the breaking-changes history. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MeheJtyQwUzJGLcYpyWURD --- CLAUDE.md | 10 +- README.md | 2 +- docs/history/llama-cpp-breaking-changes.md | 2 + llama/CMakeLists.txt | 4 +- .../0001-win32-arg-parse-embed-guard.patch | 40 ++-- .../0007-server-attach-http-frontend.patch | 182 +++++------------- .../llama/value/LlamaCppVersion.java | 8 +- 7 files changed, 80 insertions(+), 168 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index de61a6dbf..2a96de04a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Java bindings for [llama.cpp](https://github.com/ggerganov/llama.cpp) via JNI, providing a high-level API for LLM inference in Java. The Java layer communicates with a native C++ library through JNI. -Current llama.cpp pinned version: **b10107** +Current llama.cpp pinned version: **b10154** ## Upgrading CUDA Version @@ -429,7 +429,7 @@ needs no extra step here, `build-webui` re-reads the tag and rebuilds the matchi ships no UI): ```bash # needs node/npm + network; embed.cpp is plain C++17 (no npm) -git clone --depth 1 --branch b10107 https://github.com/ggml-org/llama.cpp /tmp/lc +git clone --depth 1 --branch b10154 https://github.com/ggml-org/llama.cpp /tmp/lc ( cd /tmp/lc/tools/ui && npm ci && npm run build \ && ( cd dist && find . -type f -not -path './_gzip/*' \ | while read -r f; do mkdir -p "_gzip/$(dirname "$f")"; gzip -9 -c "$f" > "_gzip/$f"; done ) \ @@ -469,7 +469,7 @@ cache lives in **Depot Cache** over sccache's **WebDAV** backend: - `SCCACHE_WEBDAV_TOKEN: ${{ secrets.DEPOT_TOKEN }}` — a Depot **organization** token, stored as the repo secret **`DEPOT_TOKEN`**. -Because `sccache` is **content-addressed** and llama.cpp is pinned (`GIT_TAG b10107`), the +Because `sccache` is **content-addressed** and llama.cpp is pinned (`GIT_TAG b10154`), the ~280 upstream object files are byte-identical every run, so a warm cache recompiles only the *changed* files. Depot's cache is **shared across all branches** (unlike GitHub's per-branch `actions/cache`), so every branch builds incrementally; a `b` version bump @@ -580,7 +580,7 @@ Current patches: | `0001-win32-arg-parse-embed-guard.patch` | Windows JNI regression from llama.cpp **#24779** (introduced b9739): on Windows `common_params_parse` re-derived argv from the **process** command line (`GetCommandLineW`) and adopted it, so an embedded/JNI caller (`java.exe`) lost its `--model …` args → "Failed to parse model parameters". b9789 narrowed the unconditional override to a **count-guard** (`if (static_cast(utf8.buf.size()) == argc) { argv = utf8.ptrs.data(); }`), but that is exactly the variant the project already found breaks its Windows server-integration tests (when the embedded argv length coincides with `java.exe`'s). The patch carries the **complete upstream change** (so it can be submitted to llama.cpp verbatim and then dropped here): **(1)** `common_params_parse` parses **exactly the argv it is given** (no `GetCommandLineW` magic) and a new `common_params_parse_main()` wrapper holds the UTF-8 recovery for the standalone tools' `main()` (`common/arg.{cpp,h}`); **(2)** the **~34 standalone `main()` call sites** (every `common_params_parse(argc, argv, …)` across `tools/*`, `examples/*` and the `tests/*` programs) flip to `common_params_parse_main()`; **(3)** a `tests/test-arg-parser.cpp` regression case pins that `common_params_parse` honors a caller-supplied argv. The embedded caller (`jllama.cpp`) keeps calling `common_params_parse` and is never overridden. **Our subproject build compiles only the `arg.{cpp,h}` core** — `LLAMA_BUILD_TOOLS`/`LLAMA_BUILD_TESTS` are OFF for a FetchContent subproject — so the flips + test are applied-but-not-compiled here; they were validated via a one-off `-DLLAMA_BUILD_TOOLS=ON -DLLAMA_BUILD_TESTS=ON` build (the new test compiles and its asserts pass; `test-arg-parser`'s only red there is the live `ggml.ai` download check, which is sandbox-network, not the patch). Because it spans **37 files** it must be refreshed on every llama.cpp bump (the applier fails loud). | | `0002-server-preserve-caller-load-progress-callback.patch` | Load-progress-callback regression introduced in llama.cpp **b9789**: `server_context::load_model` (`tools/server/server-context.cpp`) now **unconditionally** installs the server's own load-progress reporter on `params_base.load_progress_callback` immediately before `common_init_from_params`, clobbering any callback the embedding caller already set. libjllama's `LoadProgressCallback` feature wires `common_params.load_progress_callback` to a JNI trampoline *before* calling `load_model`, so the bump silently killed it — `LoadProgressCallbackTest` saw zero progress updates and the abort-on-`false` path never threw. The patch guards the assignment with `if (params_base.load_progress_callback == nullptr)`, so the server installs its own reporter **only when the caller hasn't** — a caller-supplied callback survives and fires during load. Standalone `llama-server` (no caller callback, so the field is null) is unaffected. Same JNI-vs-standalone divergence class as `0001`. | | `0003-pr22393-server-add-slot-prompt-similarity-getter-setter.patch` | **Upstream-PR carry** of [ggml-org/llama.cpp#22393](https://github.com/ggml-org/llama.cpp/pull/22393) ("server : add slot_prompt_similarity getter/setter") while it is still open upstream. Purely additive: adds `server_context::get_slot_prompt_similarity()` / `set_slot_prompt_similarity(float)` (`tools/server/server-context.{cpp,h}`) so an embedding/JNI caller can query and tune the slot-selection threshold at runtime without reloading the model. Verbatim copy of the PR — drop it once a pinned `b` includes the change. | -| `0007-server-attach-http-frontend.patch` | **Adds `llama_server_attach(argc, argv, server_context&)`** so the `NativeServer` *attach mode* can serve an **already-loaded `LlamaModel`** over the full upstream HTTP frontend — no second model load, no `start_loop()`; the LlamaModel's worker keeps driving the shared `server_context` and the HTTP routes post tasks to its queue (the queue is the synchronization point). Mechanically: (1) extracts the common route table + the CORS-proxy/tools **route bindings** out of `llama_server()` into `llama_server_register_common_routes(...)` (shared, so the entry points cannot drift; returns `false` on tools-setup failure) — the per-caller **experimental-feature warnings** (upstream's b10015/#25655 `cors_origins` security warning + the router/MCP/tools `warn_names` block) stay in `llama_server` since they depend on router state the shared helper does not carry; (2) adds `llama_server_attach`, which parses only the HTTP-side argv via `common_params_parse`, starts `g_stream_sessions` GC + `server_http_context`, registers the common routes plus the non-router resumable-streaming handlers, marks ready immediately (model already loaded), and blocks on the HTTP thread until `llama_server_request_shutdown()` — never calling `common_init()`, backend init, `ctx_server.terminate()` or `llama_backend_free()` (the embedding caller owns those). Applies after `0001`+`0006` (same file); closes the "NativeServer — reuse an already-loaded LlamaModel" TODO. Upstream-submittable ("server: let embedding callers attach the HTTP frontend to an existing server_context"). | +| `0007-server-attach-http-frontend.patch` | **Adds `llama_server_attach(argc, argv, server_context&)`** so the `NativeServer` *attach mode* can serve an **already-loaded `LlamaModel`** over the upstream HTTP frontend — no second model load, no `start_loop()`; the LlamaModel's worker keeps driving the shared `server_context` and the HTTP routes post tasks to its queue (the queue is the synchronization point). Mechanically: (1) extracts the **pure core route table** (`health` … `slots`) out of `llama_server()` into `static void llama_server_register_common_routes(ctx_http, routes)` (shared, so the two entry points cannot drift on the core endpoint set). **Scope note (narrowed at the b10154 bump):** the helper deliberately carries **only** the stable, state-independent route table — **not** the resumable-streaming routes (their handlers differ between router / non-router), the GCP-compat shim, or the experimental **CORS-proxy / MCP-server / built-in-tools** wiring. b10154 (upstream MCP-server support) moved the streaming routes into the middle of that block and coupled tools/CORS to a per-call `server_mcp mcp_mgr` lifecycle, so the earlier contiguous "route-table + CORS-proxy + tools" extraction is no longer possible; `llama_server()` keeps all of that inline, **byte-identical to upstream b10154** (only the route-table block is factored out). (2) adds `llama_server_attach`, which parses only the HTTP-side argv via `common_params_parse`, starts the stream-session GC + `server_http_context`, registers the common route table, the **non-router** resumable-streaming handlers (upstream b10154 paths `/v1/stream` GET/DEL + `/v1/streams/lookup` POST), the GCP-compat shim, and **403 "disabled" stubs for `/cors-proxy` + `/tools`** (attach mode does not wire the experimental CORS-proxy / MCP / built-in-tools host — those belong to a full `llama-server`, not an embedded model), marks ready immediately (model already loaded), and blocks on the HTTP thread until `llama_server_request_shutdown()` — never calling `common_init()`, backend init, `ctx_server.terminate()` or `llama_backend_free()` (the embedding caller owns those). Applies after `0001`+`0006` (same file); closes the "NativeServer — reuse an already-loaded LlamaModel" TODO. Upstream-submittable ("server: let embedding callers attach the HTTP frontend to an existing server_context"). | | `0008-server-models-worker-cmd-override.patch` | **Makes router mode usable in-JVM.** The router (`server-models.cpp`) spawns each model worker by re-executing its own binary (`get_server_exec_path()` = `/proc/self/exe` & friends) — inside a JVM that binary is `java`, not a llama-server, so embedded router workers could never start. The patch adds env `LLAMA_SERVER_WORKER_CMD` (whitespace-split; read in `server_model_meta::update_args`) which replaces only the leading binary-path token of the rendered worker args, letting an embedding host relaunch workers through its own bootstrap — e.g. `java -cp app.jar net.ladenthin.llama.server.NativeServer` (each worker is then a fresh JVM running the classic single-model `NativeServer`). Exposed in Java as `NativeServer.setWorkerCommand(String...)` (JNI `setenv`); exercised by `RouterModeIntegrationTest` (Linux CI). Upstream-submittable (also useful for containerized/wrapped deployments). | | `0006-server-embed-native-server-jni.patch` | **Makes `server.cpp`'s `llama_server` embeddable in the JVM** so the `NativeServer` JNI bridge can run the full upstream HTTP server (WebUI included) inside `libjllama` — see "Two server modes" below. b9870 already exposes `int llama_server(int, char**)` (non-static; no `main` in the file), so the patch only adds embedded-mode support: (1) a `g_llama_server_embedded` flag + `llama_server_set_embedded()` / `llama_server_request_shutdown()` (declared in the committed `src/main/cpp/native_server_bridge.h`); (2) skips installing the process-wide SIGINT/SIGTERM handlers when embedded (they would hijack the JVM's); (3) in embedded mode parses the **forwarded** argv via `common_params_parse` instead of `common_params_parse_main` (whose `GetCommandLineW` recovery would pick up `java.exe`'s command line — the same Windows class of bug `0001` fixes). `llama_server_request_shutdown()` mirrors the SIGTERM path (invokes the installed `shutdown_handler` → `ctx_server.terminate()` unblocks `start_loop()`), giving JNI an out-of-band stop since `ctx_server` is loop-local. Applies **after `0001`** (which flips this call site to `common_params_parse_main`), so its context is the post-`0001` tree; regenerate against `0001`+source on a bump. Only touches `tools/server/server.cpp`. | @@ -1262,7 +1262,7 @@ ctest --test-dir build --output-on-failure -R "ResultsToJson" #### Upstream source location (in CMake build tree) -llama.cpp is fetched via CMake FetchContent, pinned to `GIT_TAG b10107`. +llama.cpp is fetched via CMake FetchContent, pinned to `GIT_TAG b10154`. **GoogleTest** is a separate `BUILD_TESTING`-only FetchContent (`GIT_TAG v1.17.0`), used solely by the `jllama_test` C++ unit-test binary — not by the shipped library, and not coupled to the diff --git a/README.md b/README.md index 57bd8928d..2921e8a5a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ **Build:** ![Java 8+](https://img.shields.io/badge/Java-8%2B-informational) ![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20macOS%20%7C%20Windows%20%7C%20Android-lightgrey) -[![llama.cpp b10107](https://img.shields.io/badge/llama.cpp-%23b10107-informational)](https://github.com/ggml-org/llama.cpp/releases/tag/b10107) +[![llama.cpp b10154](https://img.shields.io/badge/llama.cpp-%23b10154-informational)](https://github.com/ggml-org/llama.cpp/releases/tag/b10154) [![JPMS](https://img.shields.io/badge/JPMS-modular%20JAR-25A162)](https://openjdk.org/projects/jigsaw/) ![JUnit](https://img.shields.io/badge/tested%20with-JUnit6-25A162) [![JSpecify](https://img.shields.io/badge/JSpecify-1.0.0%20%40NullMarked-25A162)](https://jspecify.dev) diff --git a/docs/history/llama-cpp-breaking-changes.md b/docs/history/llama-cpp-breaking-changes.md index 9b2ff23a7..3eb658241 100644 --- a/docs/history/llama-cpp-breaking-changes.md +++ b/docs/history/llama-cpp-breaking-changes.md @@ -513,3 +513,5 @@ Used during `llama.cpp` version bumps: when upgrading, scan this file from the r | b10076–b10092 | upstream verification (sandbox) | All **six** patches (`0001`–`0003`, `0006`–`0008`) re-verified against a clean b10092 checkout (ggml/llama.cpp commit `3ce7da2c8`): applied in filename order via `git apply`, all clean — the `b10076...b10092` diff's two patch-target files (`common/arg.cpp`, `tools/server/server-context.cpp`) changed only outside the patched regions (`0001`'s `common_params_parse*` block and `0002`/`0003`'s `load_model`/getter regions untouched), `0006`/`0007`'s `tools/server/server.cpp` and `0008`'s `tools/server/server-models.cpp` unchanged (`0006`'s standalone `git apply --check` fails only because its context is the post-`0001` tree, as documented). The OuteTTS generator ran clean against `tools/tts/tts.cpp @ b10092` (all anchors held, generated TU written). Per-platform build + `ctest` confirmation by the CI pipeline. | | b10092–b10107 | `common/common.h` + `include/llama.h` (**public-API break**) + `common/{arg.cpp,chat.cpp,common.cpp,fit.cpp}` + `ggml/src/{ggml-cuda/{common.cuh,mmq.cu,mmq.cuh,quantize.cu,quantize.cuh},ggml-hexagon/**,ggml-metal/ggml-metal-device.m}` + `src/{llama.cpp,llama-model.cpp,llama-model-loader.{cpp,h},llama-quant.cpp}` + `tools/{llama-bench/llama-bench.cpp,mtmd/mtmd-helper.cpp}` + `examples/{training/finetune.cpp,diffusion/diffusion-cli.cpp}` + `tools/ui/**` | **First real public-API break in many ranges (80 files, ~39.5k insertions, 15 commits).** Upstream PR [#20834](https://github.com/ggml-org/llama.cpp/pull/20834) (commit `e6dd0e29`, "args: refactor mlock/mmap/directio into load-mode") **removed the `use_mmap` / `use_mlock` / `use_direct_io` booleans from both `common_params` (`common/common.h`) and `llama_model_params` (`include/llama.h`)** and replaced them with a single `enum llama_load_mode load_mode` (values `NONE`/`MMAP`/`MLOCK`/`DIRECT_IO`), plus new `llama_load_mode_name()` / `llama_load_mode_from_str()` API and a `load_mode` copy in `common_model_params_to_llama` (`common/common.cpp`). **Required one project source change:** `llama/src/main/cpp/train_engine.cpp` set `params.use_mmap = false` to force writable weights for training → now `params.load_mode = LLAMA_LOAD_MODE_NONE` (mirrors upstream `finetune.cpp`'s identical flip in the same range). The **Java layer is unaffected**: `ModelFlag.MLOCK` / `NO_MMAP` emit the `--mlock` / `--no-mmap` CLI flags, which `common/arg.cpp` still accepts (now deprecated, they set `load_mode`) — `common/arg.h` is byte-identical. The other **six** priority-8 headers (`common/{chat.h,speculative.h,arg.h,download.h}`, `tools/mtmd/mtmd.h`, `include/llama-cpp.h`) are **byte-identical**. No patch-target file changed (`common/arg.cpp` moved only in the deprecated-flag region, well away from `0001`'s parse block; `tools/server/{server.cpp,server-context.cpp,server-models.cpp}` all identical), so all **six** patches (`0001`–`0003`, `0006`–`0008`) apply unchanged. The bulk is ggml backend work (CUDA MMQ/quantize rework, Hexagon `act-ops` rewrite, Metal device tweak), an internal `llama-model-loader` refactor, a `llama-bench` cleanup, and the auto-followed `tools/ui` WebUI. No OuteTTS generator anchor touched (`tools/tts/tts.cpp` unchanged). b10107 is the topmost release at bump time. | | b10092–b10107 | project source change (`train_engine.cpp`) + upstream verification (sandbox) | `train_engine.cpp` updated for the `use_mmap`→`load_mode` API break (see the row above); `LLAMA_LOAD_MODE_NONE` resolves via the already-included `llama.h`. All **six** patches (`0001`–`0003`, `0006`–`0008`) re-verified against a clean b10107 checkout (ggml/llama.cpp commit `c0bc8591`): applied in filename order via `git apply`, all clean — no patch-target file changed in the range (`0006`'s standalone `git apply --check` fails only because its context is the post-`0001` tree, as documented). The OuteTTS generator anchors hold (`tools/tts/tts.cpp` unchanged). Per-platform build + `ctest` confirmation by the CI pipeline. | +| b10107–b10154 | `common/{common.h,chat.h,chat.cpp,arg.cpp,arg.h}` + `tools/server/server.cpp` (**patch-target restructure — MCP-server support**) + new `common/{subproc.*,trie.*}` + `ggml/**` backends + `tools/ui/**` | **Two local patches refreshed; no project-source change (47 commits, ~100 files, ~5k line changes).** Upstream added **MCP-server support** ([#26170](https://github.com/ggml-org/llama.cpp/pull/26170) et al.): `common/arg.{cpp,h}` gain `common_print_available_devices()` + `--mcp-servers-config`/`--mcp-servers-json`; `common/{common.h,chat.h,chat.cpp}` change `thinking_end_tag` → `thinking_end_tags` (vector) and add `mcp_servers_*` fields (reasoning-budget internals — inside upstream-compiled `llama-common`/chat TUs, not referenced by project source). In `tools/server/server.cpp`, `llama_server()` gains a `server_mcp mcp_mgr` lifecycle (`mcp_mgr.start()`, **2-arg** `tools.setup(server_tools, mcp_mgr)` — was 1-arg — `mcp_mgr.shutdown()` in the cleanup lambdas) + a "MCP servers (experimental)" warn branch, and the resumable-streaming routes were **renamed** `/v1/stream/:conv_id` → `/v1/stream` and **moved** into the middle of the route/CORS/tools block. **Patch `0001` refreshed:** one `common/arg.h` hunk drifted (b10154 inserted `common_print_available_devices()` between `common_params_parse` and `common_params_to_map`); the other 36 files (incl. `common/arg.cpp`, the ~34 `common_params_parse_main` call sites, `tests/test-arg-parser.cpp`, `tools/server/server.cpp`, `tools/tts/tts.cpp`) applied unchanged. **Patch `0007` reworked** (the MCP-server restructure broke its contiguous extraction): the shared helper `llama_server_register_common_routes()` was **narrowed to the pure core route table** (`health` … `slots`) — `llama_server()` now keeps the streaming/GCP/CORS-proxy/MCP/tools blocks inline, **byte-identical to upstream b10154** (only the route-table block is factored out) — and `llama_server_attach()` registers the route table + non-router streaming on the new `/v1/stream` paths + GCP compat + 403 stubs for the experimental `/cors-proxy` + `/tools` endpoints it does not wire. `0002`/`0003`/`0006`/`0008` applied unchanged. b10154 is the topmost release at bump time. | +| b10107–b10154 | patch refresh (`0001`,`0007`) + upstream verification (sandbox) | Both refreshed patches + `0002`/`0003`/`0006`/`0008` re-verified against a clean b10154 checkout (ggml/llama.cpp commit `0e4a03622`): applied in filename order via `git apply`, all clean, no rejects; the fail-loud `PATCH_COMMAND` (`apply-llama-patches.cmake`) and the OuteTTS generator (`tts.cpp @ b10154`, all anchors held) both passed on a fresh `cmake -B build -DBUILD_TESTING=ON`. **Full `jllama` shared-library build (compile + link) verified locally** (`libjllama.so`, `-O3`) — the reworked `server.cpp` (helper + `llama_server_attach`) and all project TUs compile and **link** against b10154 (no undefined references), confirming the MCP-server-era API surface. No project source needed changing (`train_engine.cpp`'s prior `load_mode` fix from b10092–b10107 still holds). Per-platform build + `ctest` confirmation by the CI pipeline. | diff --git a/llama/CMakeLists.txt b/llama/CMakeLists.txt index c3922e737..b94f16cc2 100644 --- a/llama/CMakeLists.txt +++ b/llama/CMakeLists.txt @@ -173,7 +173,7 @@ set(LLAMA_BUILD_APP OFF CACHE BOOL "" FORCE) FetchContent_Declare( llama.cpp GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b10107 + GIT_TAG b10154 PATCH_COMMAND ${CMAKE_COMMAND} -DPATCH_DIR=${CMAKE_CURRENT_SOURCE_DIR}/patches -DLLAMA_SRC= @@ -196,7 +196,7 @@ execute_process( COMMAND ${CMAKE_COMMAND} -DTTS_SRC=${llama.cpp_SOURCE_DIR}/tools/tts/tts.cpp -DOUT_CPP=${JLLAMA_TTS_GEN_CPP} - -DLLAMA_TAG=b10107 + -DLLAMA_TAG=b10154 -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate-tts-upstream.cmake RESULT_VARIABLE JLLAMA_TTS_GEN_RESULT ) diff --git a/llama/patches/0001-win32-arg-parse-embed-guard.patch b/llama/patches/0001-win32-arg-parse-embed-guard.patch index 252451cdd..54a779f41 100644 --- a/llama/patches/0001-win32-arg-parse-embed-guard.patch +++ b/llama/patches/0001-win32-arg-parse-embed-guard.patch @@ -1,8 +1,8 @@ diff --git a/common/arg.cpp b/common/arg.cpp -index a26093199..61fdfabb1 100644 +index 79480e06f..ed7793b4d 100644 --- a/common/arg.cpp +++ b/common/arg.cpp -@@ -1051,14 +1051,10 @@ static utf8_argv make_utf8_argv() { +@@ -1201,14 +1201,10 @@ static utf8_argv make_utf8_argv() { #endif bool common_params_parse(int argc, char ** argv, common_params & params, llama_example ex, void(*print_usage)(int, char **)) { @@ -21,7 +21,7 @@ index a26093199..61fdfabb1 100644 auto ctx_arg = common_params_parser_init(params, ex, print_usage); const common_params params_org = ctx_arg.params; // the example can modify the default params -@@ -1091,6 +1087,21 @@ bool common_params_parse(int argc, char ** argv, common_params & params, llama_e +@@ -1242,6 +1238,21 @@ bool common_params_parse(int argc, char ** argv, common_params & params, llama_e return true; } @@ -44,7 +44,7 @@ index a26093199..61fdfabb1 100644 std::vector supported_tmpl; int32_t res = llama_chat_builtin_templates(nullptr, 0); diff --git a/common/arg.h b/common/arg.h -index 54a38b9cc..04e934f6c 100644 +index 8f609e356..62c615d29 100644 --- a/common/arg.h +++ b/common/arg.h @@ -123,6 +123,11 @@ struct common_params_context { @@ -56,8 +56,8 @@ index 54a38b9cc..04e934f6c 100644 +// callers that supply their own argv must call common_params_parse() directly. +bool common_params_parse_main(int argc, char ** argv, common_params & params, llama_example ex, void(*print_usage)(int, char **) = nullptr); + - // parse input arguments from CLI into a map - bool common_params_to_map(int argc, char ** argv, llama_example ex, std::map & out_map); + // load all backends and print the list of available (non-CPU) devices to stdout + void common_print_available_devices(); diff --git a/examples/batched/batched.cpp b/examples/batched/batched.cpp index 830e45f5a..15b6910d7 100644 @@ -86,7 +86,7 @@ index 761e7a2db..c955241ea 100644 } diff --git a/examples/diffusion/diffusion-cli.cpp b/examples/diffusion/diffusion-cli.cpp -index 86ebbf88c..a4d5b04bb 100644 +index d58d22eff..1ab28accd 100644 --- a/examples/diffusion/diffusion-cli.cpp +++ b/examples/diffusion/diffusion-cli.cpp @@ -108,7 +108,7 @@ int main(int argc, char ** argv) { @@ -255,7 +255,7 @@ index f7fa5e306..36f14bf45 100644 } diff --git a/examples/training/finetune.cpp b/examples/training/finetune.cpp -index 0a75ac110..bdf13ba6a 100644 +index 44b284391..f99918aa0 100644 --- a/examples/training/finetune.cpp +++ b/examples/training/finetune.cpp @@ -22,7 +22,7 @@ int main(int argc, char ** argv) { @@ -268,10 +268,10 @@ index 0a75ac110..bdf13ba6a 100644 } diff --git a/tests/test-arg-parser.cpp b/tests/test-arg-parser.cpp -index e83ee85dd..f8605657d 100644 +index 1d3584f90..48cf43fd8 100644 --- a/tests/test-arg-parser.cpp +++ b/tests/test-arg-parser.cpp -@@ -113,6 +113,15 @@ static void test(void) { +@@ -112,6 +112,15 @@ static void test(void) { assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), params, LLAMA_EXAMPLE_COMMON)); assert(params.model.path == "model_file.gguf"); @@ -288,7 +288,7 @@ index e83ee85dd..f8605657d 100644 assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), params, LLAMA_EXAMPLE_COMMON)); assert(params.cpuparams.n_threads == 1234); diff --git a/tests/test-export-graph-ops.cpp b/tests/test-export-graph-ops.cpp -index 7d8118dcd..88b76410f 100644 +index 46ded1398..d5f1cabe7 100644 --- a/tests/test-export-graph-ops.cpp +++ b/tests/test-export-graph-ops.cpp @@ -131,7 +131,7 @@ int main(int argc, char ** argv) { @@ -301,7 +301,7 @@ index 7d8118dcd..88b76410f 100644 } diff --git a/tests/test-recurrent-state-rollback.cpp b/tests/test-recurrent-state-rollback.cpp -index be19316db..26a041aea 100644 +index 8e2eace6a..d7a7afed9 100644 --- a/tests/test-recurrent-state-rollback.cpp +++ b/tests/test-recurrent-state-rollback.cpp @@ -44,7 +44,7 @@ int main(int argc, char ** argv) { @@ -314,10 +314,10 @@ index be19316db..26a041aea 100644 } diff --git a/tests/test-save-load-state.cpp b/tests/test-save-load-state.cpp -index b097d752a..bbafc5234 100644 +index 6e93ce6fb..9caab1653 100644 --- a/tests/test-save-load-state.cpp +++ b/tests/test-save-load-state.cpp -@@ -281,7 +281,7 @@ int main(int argc, char ** argv) { +@@ -358,7 +358,7 @@ int main(int argc, char ** argv) { common_init(); @@ -366,10 +366,10 @@ index e2dcd0b2e..0fdecd02c 100644 } diff --git a/tools/cli/cli.cpp b/tools/cli/cli.cpp -index d974a4019..98a1bdd75 100644 +index dcdb6aeac..0f4a2d188 100644 --- a/tools/cli/cli.cpp +++ b/tools/cli/cli.cpp -@@ -371,7 +371,7 @@ int llama_cli(int argc, char ** argv) { +@@ -37,7 +37,7 @@ int llama_cli(int argc, char ** argv) { common_init(); @@ -457,10 +457,10 @@ index b88a16f0f..db4facf3d 100644 } diff --git a/tools/mtmd/mtmd-cli.cpp b/tools/mtmd/mtmd-cli.cpp -index 8704ea79d..eecbaaeb0 100644 +index 08288c868..54ee01c66 100644 --- a/tools/mtmd/mtmd-cli.cpp +++ b/tools/mtmd/mtmd-cli.cpp -@@ -375,7 +375,7 @@ int main(int argc, char ** argv) { +@@ -376,7 +376,7 @@ int main(int argc, char ** argv) { common_init(); @@ -496,10 +496,10 @@ index f2179ed27..6d958a861 100644 } if (params.out_file.empty()) { diff --git a/tools/server/server.cpp b/tools/server/server.cpp -index 9e8603be6..e81ecba3f 100644 +index a3b2a8b0f..80d6a3ff6 100644 --- a/tools/server/server.cpp +++ b/tools/server/server.cpp -@@ -87,7 +87,7 @@ int llama_server(int argc, char ** argv) { +@@ -102,7 +102,7 @@ int llama_server(int argc, char ** argv) { // touch it. lifecycle is symmetric, stop_gc() runs in clean_up() before backend free server_stream_session_manager_start(); diff --git a/llama/patches/0007-server-attach-http-frontend.patch b/llama/patches/0007-server-attach-http-frontend.patch index 7ada3bb34..ebc03b7d8 100644 --- a/llama/patches/0007-server-attach-http-frontend.patch +++ b/llama/patches/0007-server-attach-http-frontend.patch @@ -1,5 +1,5 @@ diff --git a/tools/server/server.cpp b/tools/server/server.cpp -index dc9e718..47da913 100644 +index ce1d239c3..b242fc48a 100644 --- a/tools/server/server.cpp +++ b/tools/server/server.cpp @@ -63,6 +63,7 @@ int llama_server(int argc, char ** argv); @@ -10,22 +10,18 @@ index dc9e718..47da913 100644 void llama_server_terminate(); void llama_server_terminate() { if (shutdown_handler) { -@@ -107,6 +108,102 @@ static server_http_context::handler_t ex_wrapper(server_http_context::handler_t +@@ -107,6 +108,57 @@ static server_http_context::handler_t ex_wrapper(server_http_context::handler_t }; } -+// [jllama] Route table shared by the standalone single-model server, the router, and the -+// embedded attach mode (llama_server_attach below). Extracted verbatim from llama_server() so the -+// entry points cannot drift. The resumable-streaming routes are NOT registered here: their -+// handlers differ between router and non-router mode, so each entry point wires its own. The -+// experimental-feature WARNINGS (CORS/router/tools) are likewise logged per-entry-point, since -+// they depend on router state the helper does not carry; the helper only binds the routes. Returns -+// false when the experimental built-in tools were requested but failed to set up. -+[[nodiscard]] static bool llama_server_register_common_routes( -+ server_http_context & ctx_http, -+ server_routes & routes, -+ const common_params & params, -+ server_tools & tools) { ++// [jllama] Pure route table shared by the standalone single-model server and the embedded ++// attach mode (llama_server_attach below), extracted verbatim from llama_server() so the two ++// entry points cannot drift on the core endpoint set. Only the stable, state-independent ++// routes live here (health .. slots); the resumable-streaming routes (handlers differ by ++// router vs non-router), the GCP-compat shim and the experimental CORS-proxy / MCP / ++// built-in-tools wiring stay in each entry point, since upstream couples them to per-call ++// state (server_mcp mcp_mgr lifecycle, is_router_server). ++static void llama_server_register_common_routes(server_http_context & ctx_http, server_routes & routes) { + ctx_http.get ("/health", ex_wrapper(routes.get_health)); // public endpoint (no API key check) + ctx_http.get ("/v1/health", ex_wrapper(routes.get_health)); // public endpoint (no API key check) + ctx_http.get ("/metrics", ex_wrapper(routes.get_metrics)); @@ -67,53 +63,12 @@ index dc9e718..47da913 100644 + // Save & load slots + ctx_http.get ("/slots", ex_wrapper(routes.get_slots)); + ctx_http.post("/slots/:id_slot", ex_wrapper(routes.post_slots)); -+ -+ // Google Cloud Platform (Vertex AI) compat -+ ctx_http.register_gcp_compat(); -+ -+ // return 403 for disabled features -+ server_http_context::handler_t res_403 = [](const server_http_req &) { -+ auto res = std::make_unique(); -+ res->status = 403; -+ res->data = safe_json_to_str({ -+ {"error", { -+ {"message", "this feature is disabled"}, -+ {"type", "feature_disabled"}, -+ }} -+ }); -+ return res; -+ }; -+ -+ // CORS proxy (EXPERIMENTAL, only used by the Web UI for MCP) -+ if (params.ui_mcp_proxy) { -+ ctx_http.get ("/cors-proxy", ex_wrapper(proxy_handler_get)); -+ ctx_http.post("/cors-proxy", ex_wrapper(proxy_handler_post)); -+ } else { -+ ctx_http.get ("/cors-proxy", ex_wrapper(res_403)); -+ ctx_http.post("/cors-proxy", ex_wrapper(res_403)); -+ } -+ -+ // EXPERIMENTAL built-in tools -+ if (!params.server_tools.empty()) { -+ try { -+ tools.setup(params.server_tools); -+ } catch (const std::exception & e) { -+ SRV_ERR("tools setup failed: %s\n", e.what()); -+ return false; -+ } -+ ctx_http.get ("/tools", ex_wrapper(tools.handle_get)); -+ ctx_http.post("/tools", ex_wrapper(tools.handle_post)); -+ } else { -+ ctx_http.get ("/tools", ex_wrapper(res_403)); -+ ctx_http.post("/tools", ex_wrapper(res_403)); -+ } -+ return true; +} + int llama_server(int argc, char ** argv) { std::setlocale(LC_NUMERIC, "C"); -@@ -250,47 +347,9 @@ int llama_server(common_params & params, int argc, char ** argv) { +@@ -258,47 +310,7 @@ int llama_server(common_params & params, int argc, char ** argv) { ctx_http.del ("/models", ex_wrapper(models_routes->del_router_models)); } @@ -158,82 +113,16 @@ index dc9e718..47da913 100644 - // Save & load slots - ctx_http.get ("/slots", ex_wrapper(routes.get_slots)); - ctx_http.post("/slots/:id_slot", ex_wrapper(routes.post_slots)); -+ if (!llama_server_register_common_routes(ctx_http, routes, params, tools)) { -+ return 1; -+ } ++ llama_server_register_common_routes(ctx_http, routes); - // resumable streaming, the conversation_id is the session identity end to end. router and - // child wire different handlers under the same paths: a child binds the local session -@@ -315,22 +374,9 @@ int llama_server(common_params & params, int argc, char ** argv) { - ctx_http.post("/v1/streams/lookup", ex_wrapper(streams_lookup_h)); - ctx_http.del ("/v1/stream/:conv_id", ex_wrapper(stream_delete_h)); - -- // Google Cloud Platform (Vertex AI) compat -- ctx_http.register_gcp_compat(); -- -- // return 403 for disabled features -- server_http_context::handler_t res_403 = [](const server_http_req &) { -- auto res = std::make_unique(); -- res->status = 403; -- res->data = safe_json_to_str({ -- {"error", { -- {"message", "this feature is disabled"}, -- {"type", "feature_disabled"}, -- }} -- }); -- return res; -- }; -- -+ // experimental-feature warnings — the CORS-proxy, /tools and health...slots routes are all -+ // bound by llama_server_register_common_routes() above; only these log lines stay here because -+ // they depend on router state (is_router_server) the shared helper does not carry. - if (params.cors_origins == "*" && params.api_keys.empty()) { - SRV_WRN("%s", "-----------------\n"); - SRV_WRN("%s", "CORS is set to allow all origins ('*') and no API key is set\n"); -@@ -339,37 +385,16 @@ int llama_server(common_params & params, int argc, char ** argv) { - SRV_WRN("%s", "-----------------\n"); - } - -- // CORS proxy (EXPERIMENTAL, only used by the Web UI for MCP) - std::vector warn_names; - if (is_router_server) { - warn_names.push_back("router mode"); - } -- - if (params.ui_mcp_proxy) { -- ctx_http.get ("/cors-proxy", ex_wrapper(proxy_handler_get)); -- ctx_http.post("/cors-proxy", ex_wrapper(proxy_handler_post)); - warn_names.push_back("MCP proxy (experimental)"); -- } else { -- ctx_http.get ("/cors-proxy", ex_wrapper(res_403)); -- ctx_http.post("/cors-proxy", ex_wrapper(res_403)); - } -- -- // EXPERIMENTAL built-in tools - if (!params.server_tools.empty()) { -- try { -- tools.setup(params.server_tools); -- } catch (const std::exception & e) { -- SRV_ERR("tools setup failed: %s\n", e.what()); -- return 1; -- } -- ctx_http.get ("/tools", ex_wrapper(tools.handle_get)); -- ctx_http.post("/tools", ex_wrapper(tools.handle_post)); - warn_names.push_back("built-in tools (experimental)"); -- } else { -- ctx_http.get ("/tools", ex_wrapper(res_403)); -- ctx_http.post("/tools", ex_wrapper(res_403)); - } -- - if (warn_names.size() > 0) { - SRV_WRN("%s", "-----------------\n"); - SRV_WRN("%s", "the following feature(s) are enabled:\n"); -@@ -538,3 +563,68 @@ int llama_server(common_params & params, int argc, char ** argv) { + // resumable streaming: a child binds the local session factories, the router binds + // proxies that resolve the owning child, see server-stream.h +@@ -556,3 +568,89 @@ int llama_server(common_params & params, int argc, char ** argv) { return 0; } + -+// [jllama] Attach the upstream HTTP frontend — full route table, WebUI assets, resumable ++// [jllama] Attach the upstream HTTP frontend — full core route table, WebUI assets, resumable +// streaming — to an ALREADY-LOADED server_context owned by an embedding caller (a LlamaModel +// driven over JNI). Unlike llama_server(): no common_init(), no backend/NUMA init, no model +// load and no start_loop() — the caller's worker thread keeps driving the context, the HTTP @@ -241,7 +130,10 @@ index dc9e718..47da913 100644 +// HTTP-relevant argv (--host/--port/--api-key/...; no -m). Blocks until +// llama_server_request_shutdown(); never terminates the shared server_context or frees the +// backend — the embedding caller owns both. Shares shutdown_handler with llama_server(), so the -+// single-instance-per-process rule covers both entry points. ++// single-instance-per-process rule covers both entry points. The experimental CORS-proxy / MCP ++// server / built-in-tools endpoints are NOT wired in attach mode (they belong to a full ++// llama-server host, not an embedded model); they answer 403 "disabled" like a stock build with ++// those features off. +int llama_server_attach(int argc, char ** argv, server_context & ctx_server) { + std::setlocale(LC_NUMERIC, "C"); + @@ -262,16 +154,34 @@ index dc9e718..47da913 100644 + } + + server_routes routes(params, ctx_server); -+ server_tools tools; -+ if (!llama_server_register_common_routes(ctx_http, routes, params, tools)) { -+ server_stream_session_manager_stop(); -+ return 1; -+ } ++ llama_server_register_common_routes(ctx_http, routes); + -+ // single-model (non-router) resumable-streaming handlers -+ ctx_http.get ("/v1/stream/:conv_id", ex_wrapper(server_stream_make_get_handler())); ++ // single-model (non-router) resumable-streaming handlers (upstream b10154 paths) ++ ctx_http.get ("/v1/stream", ex_wrapper(server_stream_make_get_handler())); + ctx_http.post("/v1/streams/lookup", ex_wrapper(server_stream_make_lookup_handler())); -+ ctx_http.del ("/v1/stream/:conv_id", ex_wrapper(server_stream_make_delete_handler())); ++ ctx_http.del ("/v1/stream", ex_wrapper(server_stream_make_delete_handler())); ++ ++ // Google Cloud Platform (Vertex AI) compat — cheap, kept for parity with llama_server() ++ ctx_http.register_gcp_compat(); ++ ++ // return 403 for the experimental features attach mode does not wire (CORS proxy, built-in ++ // tools), so those paths answer "disabled" rather than 404 — matching a stock server built ++ // with the features off. ++ server_http_context::handler_t res_403 = [](const server_http_req &) { ++ auto res = std::make_unique(); ++ res->status = 403; ++ res->data = safe_json_to_str({ ++ {"error", { ++ {"message", "this feature is disabled"}, ++ {"type", "feature_disabled"}, ++ }} ++ }); ++ return res; ++ }; ++ ctx_http.get ("/cors-proxy", ex_wrapper(res_403)); ++ ctx_http.post("/cors-proxy", ex_wrapper(res_403)); ++ ctx_http.get ("/tools", ex_wrapper(res_403)); ++ ctx_http.post("/tools", ex_wrapper(res_403)); + + if (!ctx_http.start()) { + SRV_ERR("%s", "exiting due to HTTP server error\n"); diff --git a/llama/src/main/java/net/ladenthin/llama/value/LlamaCppVersion.java b/llama/src/main/java/net/ladenthin/llama/value/LlamaCppVersion.java index 48bf993fd..11ae43e90 100644 --- a/llama/src/main/java/net/ladenthin/llama/value/LlamaCppVersion.java +++ b/llama/src/main/java/net/ladenthin/llama/value/LlamaCppVersion.java @@ -10,13 +10,13 @@ * library was compiled against, exposed as a compile-time constant so callers can render a badge or * emit a startup log line without loading the native library. * - *

{@link #LLAMA_CPP_VERSION} is a pure-Java string ({@code "b10107"}) that mirrors the + *

{@link #LLAMA_CPP_VERSION} is a pure-Java string ({@code "b10154"}) that mirrors the * {@code GIT_TAG} in {@code llama/CMakeLists.txt}. It is available even when {@code libjllama} is * absent (pure-Java checkout, before {@code System.load}), which is what makes it suitable for a * lightweight version badge in Android or other UIs.

* *

For the authoritative value that is baked into the native binary — the build number - * plus the resolved upstream commit, e.g. {@code "b10107-"} — call + * plus the resolved upstream commit, e.g. {@code "b10154-"} — call * {@link net.ladenthin.llama.LlamaModel#getLlamaCppBuildInfo()} instead; that reads llama.cpp's own * {@code build-info} through JNI and therefore cannot drift from the compiled library (but requires * the native library to be loaded).

@@ -24,14 +24,14 @@ public final class LlamaCppVersion { /** - * The pinned llama.cpp release tag this library was built against, e.g. {@code "b10107"}. + * The pinned llama.cpp release tag this library was built against, e.g. {@code "b10154"}. * *

Kept in lockstep with {@code GIT_TAG} in {@code llama/CMakeLists.txt} — see the * "Upgrading/Downgrading llama.cpp Version" checklist in {@code CLAUDE.md}. This is the * compile-time pin; use {@link net.ladenthin.llama.LlamaModel#getLlamaCppBuildInfo()} for the * value actually linked into the native binary.

*/ - public static final String LLAMA_CPP_VERSION = "b10107"; + public static final String LLAMA_CPP_VERSION = "b10154"; // Constants holder — not instantiable. private LlamaCppVersion() {}