From 6c03e46390a624b7c47ce41ad191b07d0635a644 Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Thu, 25 Jun 2026 23:42:21 +0200 Subject: [PATCH 01/12] chore: :arrow_up: Update ikawrakow/ik_llama.cpp to `b84902d2ad27c34f989f23947200c4b91b1568fd` (#10515) :arrow_up: Update ikawrakow/ik_llama.cpp Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: mudler <2420543+mudler@users.noreply.github.com> --- backend/cpp/ik-llama-cpp/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/cpp/ik-llama-cpp/Makefile b/backend/cpp/ik-llama-cpp/Makefile index 860606253..d76a07854 100644 --- a/backend/cpp/ik-llama-cpp/Makefile +++ b/backend/cpp/ik-llama-cpp/Makefile @@ -1,5 +1,5 @@ -IK_LLAMA_VERSION?=d5507e33ae7ee2b7b41475f08044d3bde3b839ee +IK_LLAMA_VERSION?=b84902d2ad27c34f989f23947200c4b91b1568fd LLAMA_REPO?=https://github.com/ikawrakow/ik_llama.cpp CMAKE_ARGS?= From 179210b9702a866ef2ab0fecb420f6b74150f80c Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 00:53:03 +0200 Subject: [PATCH 02/12] chore: bump localrecall for postgres per-connection timeouts (#10517) * chore: bump localrecall for postgres per-connection timeouts Pulls mudler/LocalRecall#49: sets lock_timeout / idle_in_transaction (default on) + opt-in statement_timeout on every pooled connection, so a corrupt/wedged index (e.g. a BM25 insert spinning on a buffer-content lock) can no longer hold its relation lock forever and head-of-line block the whole vector store. Signed-off-by: Ettore Di Giacinto Assisted-by: Claude:claude-opus-4-8 [Claude Code] * docs(agents): document PostgreSQL connection safety timeouts Note the POSTGRES_LOCK_TIMEOUT / POSTGRES_IDLE_IN_TRANSACTION_TIMEOUT / POSTGRES_STATEMENT_TIMEOUT env vars read by the embedded vector store, and that safe defaults are on automatically. Signed-off-by: Ettore Di Giacinto Assisted-by: Claude:claude-opus-4-8 [Claude Code] --------- Signed-off-by: Ettore Di Giacinto Co-authored-by: Ettore Di Giacinto --- docs/content/features/agents.md | 12 ++++++++++++ go.mod | 2 +- go.sum | 6 ++---- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/content/features/agents.md b/docs/content/features/agents.md index e6fd1d0e9..ebdb91c26 100644 --- a/docs/content/features/agents.md +++ b/docs/content/features/agents.md @@ -86,6 +86,18 @@ LOCALAI_AGENT_POOL_DATABASE_URL=postgresql://localrecall:localrecall@postgres:54 The PostgreSQL image `quay.io/mudler/localrecall:v0.5.2-postgresql` is pre-configured with pgvector and ready to use. +#### Connection safety timeouts (PostgreSQL only) + +The embedded vector store sets per-connection timeouts so a single stuck or corrupt index can never hold a lock indefinitely and stall every other collection operation. Safe defaults are applied automatically — you only need to set these to override them: + +| Variable | Default | Description | +|----------|---------|-------------| +| `POSTGRES_LOCK_TIMEOUT` | `30s` | Bounds how long a statement waits to acquire a lock, so queued statements fail fast instead of piling up. Set `0`/`off` to disable. | +| `POSTGRES_IDLE_IN_TRANSACTION_TIMEOUT` | `300s` | Reaps abandoned transactions that would otherwise pin locks. Set `0`/`off` to disable. | +| `POSTGRES_STATEMENT_TIMEOUT` | _(unset)_ | Bounds total statement runtime, auto-aborting a wedged query. Off by default since a large vector index build can exceed any fixed limit; index builds are exempted, so it is safe to enable. | + +These are read directly from the LocalAI process environment by the embedded store (the same as `DATABASE_URL` and `HYBRID_SEARCH_*`). + ### Docker Compose Example Basic setup with in-memory vector store: diff --git a/go.mod b/go.mod index 185407279..80b31bd41 100644 --- a/go.mod +++ b/go.mod @@ -221,7 +221,7 @@ require ( github.com/labstack/gommon v0.4.2 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/mudler/LocalAGI v0.0.0-20260606071251-14aed1ae4336 - github.com/mudler/localrecall v0.6.3-0.20260618142827-d0073dd5dc32 // indirect + github.com/mudler/localrecall v0.6.3-0.20260625224022-1c6a03d0c29f // indirect github.com/mudler/skillserver v0.0.7-0.20260520220837-a7317cbf9145 github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/oxffaa/gopher-parse-sitemap v0.0.0-20191021113419-005d2eb1def4 // indirect diff --git a/go.sum b/go.sum index ea32405fe..d9dc89ed0 100644 --- a/go.sum +++ b/go.sum @@ -976,10 +976,8 @@ github.com/mudler/go-piper v0.0.0-20241023091659-2494246fd9fc h1:RxwneJl1VgvikiX github.com/mudler/go-piper v0.0.0-20241023091659-2494246fd9fc/go.mod h1:O7SwdSWMilAWhBZMK9N9Y/oBDyMMzshE3ju8Xkexwig= github.com/mudler/go-processmanager v0.1.1 h1:c/1NRZOZpW8HuFv9RhBG57nQu1oDMRomEHedwBFMlrw= github.com/mudler/go-processmanager v0.1.1/go.mod h1:h6kmHUZeafr+k5hRYpGLMzJFH4hItHffgpRo2QIkP+o= -github.com/mudler/localrecall v0.6.3-0.20260606070048-9a3b3321a9cd h1:trn9D5UHAE6zdRyD2uX04W1tLSslAwozVwcyNTd72Ak= -github.com/mudler/localrecall v0.6.3-0.20260606070048-9a3b3321a9cd/go.mod h1:28k5n19raUrkuwXkacdNsBlj8yuSnGhpT16tu+2+4dU= -github.com/mudler/localrecall v0.6.3-0.20260618142827-d0073dd5dc32 h1:RP4BVGTHHpJIrGAwqRD3Wq1wmURmc1SxhwacnIWgI+g= -github.com/mudler/localrecall v0.6.3-0.20260618142827-d0073dd5dc32/go.mod h1:28k5n19raUrkuwXkacdNsBlj8yuSnGhpT16tu+2+4dU= +github.com/mudler/localrecall v0.6.3-0.20260625224022-1c6a03d0c29f h1:qCG+EherSYYHYDt6TJP8zrhAHFdRNxzTqz/UgQtATOY= +github.com/mudler/localrecall v0.6.3-0.20260625224022-1c6a03d0c29f/go.mod h1:28k5n19raUrkuwXkacdNsBlj8yuSnGhpT16tu+2+4dU= github.com/mudler/memory v0.0.0-20260406210934-424c1ecf2cf8 h1:Ry8RiWy8fZ6Ff4E7dPmjRsBrnHOnPeOOj2LhCgyjQu0= github.com/mudler/memory v0.0.0-20260406210934-424c1ecf2cf8/go.mod h1:EA8Ashhd56o32qN7ouPKFSRUs/Z+LrRCF4v6R2Oarm8= github.com/mudler/skillserver v0.0.7-0.20260520220837-a7317cbf9145 h1:z59tA3IDYPt71nzH1jpxeaA1LuDw8aZfpTQFNU43Zb8= From ae0da454a71128146856b7ed06fe8f73794c608e Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 01:02:15 +0200 Subject: [PATCH 03/12] chore: pin localrecall to tagged v0.6.3 (#10518) #10517 pinned the pseudo-version of the postgres connection-timeout fix; mudler/LocalRecall@v0.6.3 now tags that exact commit. Use the clean release tag instead of the pseudo-version. No code change. Assisted-by: Claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto Co-authored-by: Ettore Di Giacinto --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 80b31bd41..fa3608c62 100644 --- a/go.mod +++ b/go.mod @@ -221,7 +221,7 @@ require ( github.com/labstack/gommon v0.4.2 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/mudler/LocalAGI v0.0.0-20260606071251-14aed1ae4336 - github.com/mudler/localrecall v0.6.3-0.20260625224022-1c6a03d0c29f // indirect + github.com/mudler/localrecall v0.6.3 // indirect github.com/mudler/skillserver v0.0.7-0.20260520220837-a7317cbf9145 github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/oxffaa/gopher-parse-sitemap v0.0.0-20191021113419-005d2eb1def4 // indirect diff --git a/go.sum b/go.sum index d9dc89ed0..129976bbc 100644 --- a/go.sum +++ b/go.sum @@ -976,8 +976,8 @@ github.com/mudler/go-piper v0.0.0-20241023091659-2494246fd9fc h1:RxwneJl1VgvikiX github.com/mudler/go-piper v0.0.0-20241023091659-2494246fd9fc/go.mod h1:O7SwdSWMilAWhBZMK9N9Y/oBDyMMzshE3ju8Xkexwig= github.com/mudler/go-processmanager v0.1.1 h1:c/1NRZOZpW8HuFv9RhBG57nQu1oDMRomEHedwBFMlrw= github.com/mudler/go-processmanager v0.1.1/go.mod h1:h6kmHUZeafr+k5hRYpGLMzJFH4hItHffgpRo2QIkP+o= -github.com/mudler/localrecall v0.6.3-0.20260625224022-1c6a03d0c29f h1:qCG+EherSYYHYDt6TJP8zrhAHFdRNxzTqz/UgQtATOY= -github.com/mudler/localrecall v0.6.3-0.20260625224022-1c6a03d0c29f/go.mod h1:28k5n19raUrkuwXkacdNsBlj8yuSnGhpT16tu+2+4dU= +github.com/mudler/localrecall v0.6.3 h1:uXOrP9JmetzxgVKzSrawviyBHZfAcvPBBIrvVUdZjDA= +github.com/mudler/localrecall v0.6.3/go.mod h1:28k5n19raUrkuwXkacdNsBlj8yuSnGhpT16tu+2+4dU= github.com/mudler/memory v0.0.0-20260406210934-424c1ecf2cf8 h1:Ry8RiWy8fZ6Ff4E7dPmjRsBrnHOnPeOOj2LhCgyjQu0= github.com/mudler/memory v0.0.0-20260406210934-424c1ecf2cf8/go.mod h1:EA8Ashhd56o32qN7ouPKFSRUs/Z+LrRCF4v6R2Oarm8= github.com/mudler/skillserver v0.0.7-0.20260520220837-a7317cbf9145 h1:z59tA3IDYPt71nzH1jpxeaA1LuDw8aZfpTQFNU43Zb8= From 74f07ecc35106d2ea7032816045fe6c8388ec0f3 Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 01:02:48 +0200 Subject: [PATCH 04/12] fix(backends): quote $CURDIR in run.sh (fixes backends in paths with spaces) (#10519) fix(backends): quote $CURDIR in run.sh so backends work in paths with spaces The backend launcher scripts derive their own directory with CURDIR=$(dirname "$(realpath $0)") and then referenced it unquoted as $CURDIR (e.g. [ -f $CURDIR/lib/ld.so ], export LD_LIBRARY_PATH=$CURDIR/lib:..., exec $CURDIR/ "$@"). When a backend is installed under a path that contains a space - notably macOS's ~/Library/Application Support/... - bash word-splits the unquoted $CURDIR, so the test builtin fails with "binary operator expected" and exec tries to run ".../Library/Application", yielding "No such file or directory". The backend never starts, surfacing as a gRPC "service not ready" error and an HTTP 500. Quote $CURDIR (and the realpath "$0") in every affected run.sh; no logic changes. Co-authored-by: Ettore Di Giacinto Co-authored-by: Claude Opus 4.8 (1M context) --- backend/cpp/ik-llama-cpp/run.sh | 18 +++++++++--------- backend/cpp/llama-cpp/run.sh | 22 +++++++++++----------- backend/cpp/turboquant/run.sh | 20 ++++++++++---------- backend/go/acestep-cpp/run.sh | 18 +++++++++--------- backend/go/ced/run.sh | 4 ++-- backend/go/cloud-proxy/run.sh | 4 ++-- backend/go/crispasr/run.sh | 20 ++++++++++---------- backend/go/depth-anything-cpp/run.sh | 18 +++++++++--------- backend/go/local-store/run.sh | 4 ++-- backend/go/localvqe/run.sh | 20 ++++++++++---------- backend/go/locate-anything-cpp/run.sh | 18 +++++++++--------- backend/go/omnivoice-cpp/run.sh | 18 +++++++++--------- backend/go/opus/run.sh | 12 ++++++------ backend/go/parakeet-cpp/run.sh | 4 ++-- backend/go/piper/run.sh | 12 ++++++------ backend/go/qwen3-tts-cpp/run.sh | 18 +++++++++--------- backend/go/rfdetr-cpp/run.sh | 18 +++++++++--------- backend/go/sam3-cpp/run.sh | 18 +++++++++--------- backend/go/sherpa-onnx/run.sh | 16 ++++++++-------- backend/go/silero-vad/run.sh | 10 +++++----- backend/go/stablediffusion-ggml/run.sh | 18 +++++++++--------- backend/go/supertonic/run.sh | 16 ++++++++-------- backend/go/vibevoice-cpp/run.sh | 18 +++++++++--------- backend/go/voxtral/run.sh | 16 ++++++++-------- backend/go/whisper/run.sh | 18 +++++++++--------- backend/rust/kokoros/run.sh | 14 +++++++------- 26 files changed, 196 insertions(+), 196 deletions(-) diff --git a/backend/cpp/ik-llama-cpp/run.sh b/backend/cpp/ik-llama-cpp/run.sh index 1c4ee2a69..d10d19367 100644 --- a/backend/cpp/ik-llama-cpp/run.sh +++ b/backend/cpp/ik-llama-cpp/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -13,28 +13,28 @@ grep -e "flags" /proc/cpuinfo | head -1 # ik_llama.cpp requires AVX2 — default to avx2 binary BINARY=ik-llama-cpp-avx2 -if [ -e $CURDIR/ik-llama-cpp-fallback ] && ! grep -q -e "\savx2\s" /proc/cpuinfo ; then +if [ -e "$CURDIR"/ik-llama-cpp-fallback ] && ! grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 NOT found, using fallback" BINARY=ik-llama-cpp-fallback fi # Extend ld library path with the dir where this script is located/lib if [ "$(uname)" == "Darwin" ]; then - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH - #export DYLD_FALLBACK_LIBRARY_PATH=$CURDIR/lib:$DYLD_FALLBACK_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH + #export DYLD_FALLBACK_LIBRARY_PATH="$CURDIR"/lib:$DYLD_FALLBACK_LIBRARY_PATH else - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using binary: $BINARY" - exec $CURDIR/lib/ld.so $CURDIR/$BINARY "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/$BINARY "$@" fi echo "Using binary: $BINARY" -exec $CURDIR/$BINARY "$@" +exec "$CURDIR"/$BINARY "$@" # We should never reach this point, however just in case we do, run fallback -exec $CURDIR/ik-llama-cpp-fallback "$@" +exec "$CURDIR"/ik-llama-cpp-fallback "$@" diff --git a/backend/cpp/llama-cpp/run.sh b/backend/cpp/llama-cpp/run.sh index db8498f4b..09a13b0fe 100755 --- a/backend/cpp/llama-cpp/run.sh +++ b/backend/cpp/llama-cpp/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -16,37 +16,37 @@ BINARY=llama-cpp-fallback # CPU_ALL_VARIANTS: ggml's backend registry dlopens the best libggml-cpu-*.so for this # host, so no shell-side AVX probing. GPU images (cublas/sycl/vulkan/hipblas) ship only # llama-cpp-fallback (the accelerator does the compute), so fall back to it when absent. -if [ -e $CURDIR/llama-cpp-cpu-all ]; then +if [ -e "$CURDIR"/llama-cpp-cpu-all ]; then BINARY=llama-cpp-cpu-all fi if [ -n "$LLAMACPP_GRPC_SERVERS" ]; then - if [ -e $CURDIR/llama-cpp-grpc ]; then + if [ -e "$CURDIR"/llama-cpp-grpc ]; then BINARY=llama-cpp-grpc fi fi # Extend ld library path with the dir where this script is located/lib if [ "$(uname)" == "Darwin" ]; then - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH - #export DYLD_FALLBACK_LIBRARY_PATH=$CURDIR/lib:$DYLD_FALLBACK_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH + #export DYLD_FALLBACK_LIBRARY_PATH="$CURDIR"/lib:$DYLD_FALLBACK_LIBRARY_PATH else - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH # Tell rocBLAS where to find TensileLibrary data (GPU kernel tuning files) if [ -d "$CURDIR/lib/rocblas/library" ]; then - export ROCBLAS_TENSILE_LIBPATH=$CURDIR/lib/rocblas/library + export ROCBLAS_TENSILE_LIBPATH="$CURDIR"/lib/rocblas/library fi fi # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using binary: $BINARY" - exec $CURDIR/lib/ld.so $CURDIR/$BINARY "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/$BINARY "$@" fi echo "Using binary: $BINARY" -exec $CURDIR/$BINARY "$@" +exec "$CURDIR"/$BINARY "$@" # We should never reach this point, however just in case we do, run fallback -exec $CURDIR/llama-cpp-fallback "$@" \ No newline at end of file +exec "$CURDIR"/llama-cpp-fallback "$@" \ No newline at end of file diff --git a/backend/cpp/turboquant/run.sh b/backend/cpp/turboquant/run.sh index cd41a0f7f..33864385d 100755 --- a/backend/cpp/turboquant/run.sh +++ b/backend/cpp/turboquant/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,36 +15,36 @@ BINARY=turboquant-fallback # x86/arm64 ship a single turboquant-cpu-all built with ggml CPU_ALL_VARIANTS: ggml's # backend registry dlopens the best libggml-cpu-*.so for this host, so no shell-side # probing. ROCm ships only turboquant-fallback, so fall back to it when cpu-all is absent. -if [ -e $CURDIR/turboquant-cpu-all ]; then +if [ -e "$CURDIR"/turboquant-cpu-all ]; then BINARY=turboquant-cpu-all fi if [ -n "$LLAMACPP_GRPC_SERVERS" ]; then - if [ -e $CURDIR/turboquant-grpc ]; then + if [ -e "$CURDIR"/turboquant-grpc ]; then BINARY=turboquant-grpc fi fi # Extend ld library path with the dir where this script is located/lib if [ "$(uname)" == "Darwin" ]; then - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH # Tell rocBLAS where to find TensileLibrary data (GPU kernel tuning files) if [ -d "$CURDIR/lib/rocblas/library" ]; then - export ROCBLAS_TENSILE_LIBPATH=$CURDIR/lib/rocblas/library + export ROCBLAS_TENSILE_LIBPATH="$CURDIR"/lib/rocblas/library fi fi # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using binary: $BINARY" - exec $CURDIR/lib/ld.so $CURDIR/$BINARY "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/$BINARY "$@" fi echo "Using binary: $BINARY" -exec $CURDIR/$BINARY "$@" +exec "$CURDIR"/$BINARY "$@" # We should never reach this point, however just in case we do, run fallback -exec $CURDIR/turboquant-fallback "$@" +exec "$CURDIR"/turboquant-fallback "$@" diff --git a/backend/go/acestep-cpp/run.sh b/backend/go/acestep-cpp/run.sh index bcdfbc09e..c026e2051 100755 --- a/backend/go/acestep-cpp/run.sh +++ b/backend/go/acestep-cpp/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -21,20 +21,20 @@ if [ "$(uname)" = "Darwin" ]; then if [ ! -e "$LIBRARY" ]; then LIBRARY="$CURDIR/libgoacestepcpp-fallback.so" fi - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libgoacestepcpp-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libgoacestepcpp-avx.so ]; then + if [ -e "$CURDIR"/libgoacestepcpp-avx.so ]; then LIBRARY="$CURDIR/libgoacestepcpp-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libgoacestepcpp-avx2.so ]; then + if [ -e "$CURDIR"/libgoacestepcpp-avx2.so ]; then LIBRARY="$CURDIR/libgoacestepcpp-avx2.so" fi fi @@ -42,22 +42,22 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/libgoacestepcpp-avx512.so ]; then + if [ -e "$CURDIR"/libgoacestepcpp-avx512.so ]; then LIBRARY="$CURDIR/libgoacestepcpp-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export ACESTEP_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/acestep-cpp "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/acestep-cpp "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/acestep-cpp "$@" +exec "$CURDIR"/acestep-cpp "$@" diff --git a/backend/go/ced/run.sh b/backend/go/ced/run.sh index 1f95f748f..5375af4ef 100755 --- a/backend/go/ced/run.sh +++ b/backend/go/ced/run.sh @@ -4,10 +4,10 @@ set -e CURDIR=$(dirname "$(realpath "$0")") if [ "$(uname)" = "Darwin" ]; then - export DYLD_LIBRARY_PATH="$CURDIR/lib:$CURDIR:${DYLD_LIBRARY_PATH:-}" + export DYLD_LIBRARY_PATH="$CURDIR/lib:"$CURDIR":${DYLD_LIBRARY_PATH:-}" export CED_LIBRARY="$CURDIR/lib/libced.dylib" else - export LD_LIBRARY_PATH="$CURDIR/lib:$CURDIR:${LD_LIBRARY_PATH:-}" + export LD_LIBRARY_PATH="$CURDIR/lib:"$CURDIR":${LD_LIBRARY_PATH:-}" fi # If a self-contained ld.so was packaged, route through it so the packaged diff --git a/backend/go/cloud-proxy/run.sh b/backend/go/cloud-proxy/run.sh index c533c093a..efef811de 100755 --- a/backend/go/cloud-proxy/run.sh +++ b/backend/go/cloud-proxy/run.sh @@ -1,6 +1,6 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") -exec $CURDIR/cloud-proxy "$@" +exec "$CURDIR"/cloud-proxy "$@" diff --git a/backend/go/crispasr/run.sh b/backend/go/crispasr/run.sh index 6d3c4b216..078e0659f 100755 --- a/backend/go/crispasr/run.sh +++ b/backend/go/crispasr/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,20 +15,20 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/libgocrispasr-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libgocrispasr-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libgocrispasr-avx.so ]; then + if [ -e "$CURDIR"/libgocrispasr-avx.so ]; then LIBRARY="$CURDIR/libgocrispasr-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libgocrispasr-avx2.so ]; then + if [ -e "$CURDIR"/libgocrispasr-avx2.so ]; then LIBRARY="$CURDIR/libgocrispasr-avx2.so" fi fi @@ -36,12 +36,12 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/libgocrispasr-avx512.so ]; then + if [ -e "$CURDIR"/libgocrispasr-avx512.so ]; then LIBRARY="$CURDIR/libgocrispasr-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export CRISPASR_LIBRARY=$LIBRARY @@ -49,14 +49,14 @@ export CRISPASR_LIBRARY=$LIBRARY # Point piper's espeak-ng phonemizer at the bundled voice data. The variable # names the directory CONTAINING espeak-ng-data (package.sh drops it next to # this script). Harmless when espeak-ng wasn't bundled. -export CRISPASR_ESPEAK_DATA_PATH=$CURDIR +export CRISPASR_ESPEAK_DATA_PATH="$CURDIR" # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/crispasr "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/crispasr "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/crispasr "$@" +exec "$CURDIR"/crispasr "$@" diff --git a/backend/go/depth-anything-cpp/run.sh b/backend/go/depth-anything-cpp/run.sh index cbff6b0b5..8729389b4 100755 --- a/backend/go/depth-anything-cpp/run.sh +++ b/backend/go/depth-anything-cpp/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,20 +15,20 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/libdepthanythingcpp-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libdepthanythingcpp-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libdepthanythingcpp-avx.so ]; then + if [ -e "$CURDIR"/libdepthanythingcpp-avx.so ]; then LIBRARY="$CURDIR/libdepthanythingcpp-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libdepthanythingcpp-avx2.so ]; then + if [ -e "$CURDIR"/libdepthanythingcpp-avx2.so ]; then LIBRARY="$CURDIR/libdepthanythingcpp-avx2.so" fi fi @@ -36,22 +36,22 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/libdepthanythingcpp-avx512.so ]; then + if [ -e "$CURDIR"/libdepthanythingcpp-avx512.so ]; then LIBRARY="$CURDIR/libdepthanythingcpp-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export DEPTHANYTHING_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/depth-anything-cpp "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/depth-anything-cpp "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/depth-anything-cpp "$@" +exec "$CURDIR"/depth-anything-cpp "$@" diff --git a/backend/go/local-store/run.sh b/backend/go/local-store/run.sh index 479f3b486..ba0173401 100755 --- a/backend/go/local-store/run.sh +++ b/backend/go/local-store/run.sh @@ -1,6 +1,6 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") -exec $CURDIR/local-store "$@" \ No newline at end of file +exec "$CURDIR"/local-store "$@" \ No newline at end of file diff --git a/backend/go/localvqe/run.sh b/backend/go/localvqe/run.sh index d14d427c4..542885572 100755 --- a/backend/go/localvqe/run.sh +++ b/backend/go/localvqe/run.sh @@ -1,34 +1,34 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") # LocalVQE's runtime CPU-variant loader (ggml_backend_load_all) searches # get_executable_path() and current_path() — the second one is what saves us # when /proc/self/exe resolves to lib/ld.so under the bundled-loader path. -# So we cd into $CURDIR (where all the libggml-cpu-*.so files live) before +# So we cd into "$CURDIR" (where all the libggml-cpu-*.so files live) before # exec'ing the binary. cd "$CURDIR" if [ "$(uname)" = "Darwin" ]; then # macOS: LocalVQE is built as a SHARED library, so dyld needs the .dylib + # DYLD_LIBRARY_PATH. Prefer .dylib and fall back to .so just in case. - export DYLD_LIBRARY_PATH=$CURDIR:$CURDIR/lib:$DYLD_LIBRARY_PATH - LOCALVQE_LIBRARY=$CURDIR/liblocalvqe.dylib + export DYLD_LIBRARY_PATH="$CURDIR":"$CURDIR"/lib:$DYLD_LIBRARY_PATH + LOCALVQE_LIBRARY="$CURDIR"/liblocalvqe.dylib if [ ! -e "$LOCALVQE_LIBRARY" ]; then - LOCALVQE_LIBRARY=$CURDIR/liblocalvqe.so + LOCALVQE_LIBRARY="$CURDIR"/liblocalvqe.so fi export LOCALVQE_LIBRARY else - export LD_LIBRARY_PATH=$CURDIR:$CURDIR/lib:$LD_LIBRARY_PATH - export LOCALVQE_LIBRARY=$CURDIR/liblocalvqe.so + export LD_LIBRARY_PATH="$CURDIR":"$CURDIR"/lib:$LD_LIBRARY_PATH + export LOCALVQE_LIBRARY="$CURDIR"/liblocalvqe.so fi -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LOCALVQE_LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/localvqe "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/localvqe "$@" fi echo "Using library: $LOCALVQE_LIBRARY" -exec $CURDIR/localvqe "$@" +exec "$CURDIR"/localvqe "$@" diff --git a/backend/go/locate-anything-cpp/run.sh b/backend/go/locate-anything-cpp/run.sh index 4eebb3c63..3a6ccf259 100755 --- a/backend/go/locate-anything-cpp/run.sh +++ b/backend/go/locate-anything-cpp/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,20 +15,20 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/liblocateanythingcpp-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/liblocateanythingcpp-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/liblocateanythingcpp-avx.so ]; then + if [ -e "$CURDIR"/liblocateanythingcpp-avx.so ]; then LIBRARY="$CURDIR/liblocateanythingcpp-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/liblocateanythingcpp-avx2.so ]; then + if [ -e "$CURDIR"/liblocateanythingcpp-avx2.so ]; then LIBRARY="$CURDIR/liblocateanythingcpp-avx2.so" fi fi @@ -36,22 +36,22 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/liblocateanythingcpp-avx512.so ]; then + if [ -e "$CURDIR"/liblocateanythingcpp-avx512.so ]; then LIBRARY="$CURDIR/liblocateanythingcpp-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export LOCATEANYTHING_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/locate-anything-cpp "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/locate-anything-cpp "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/locate-anything-cpp "$@" +exec "$CURDIR"/locate-anything-cpp "$@" diff --git a/backend/go/omnivoice-cpp/run.sh b/backend/go/omnivoice-cpp/run.sh index 81ea2b719..706f80dd6 100755 --- a/backend/go/omnivoice-cpp/run.sh +++ b/backend/go/omnivoice-cpp/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,20 +15,20 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/libgomnivoicecpp-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libgomnivoicecpp-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libgomnivoicecpp-avx.so ]; then + if [ -e "$CURDIR"/libgomnivoicecpp-avx.so ]; then LIBRARY="$CURDIR/libgomnivoicecpp-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libgomnivoicecpp-avx2.so ]; then + if [ -e "$CURDIR"/libgomnivoicecpp-avx2.so ]; then LIBRARY="$CURDIR/libgomnivoicecpp-avx2.so" fi fi @@ -36,22 +36,22 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/libgomnivoicecpp-avx512.so ]; then + if [ -e "$CURDIR"/libgomnivoicecpp-avx512.so ]; then LIBRARY="$CURDIR/libgomnivoicecpp-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export OMNIVOICE_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/omnivoice-cpp "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/omnivoice-cpp "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/omnivoice-cpp "$@" +exec "$CURDIR"/omnivoice-cpp "$@" diff --git a/backend/go/opus/run.sh b/backend/go/opus/run.sh index d926c57d0..1a54b0c40 100644 --- a/backend/go/opus/run.sh +++ b/backend/go/opus/run.sh @@ -1,15 +1,15 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") -export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH -export OPUS_SHIM_LIBRARY=$CURDIR/lib/libopusshim.so +export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH +export OPUS_SHIM_LIBRARY="$CURDIR"/lib/libopusshim.so # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" - exec $CURDIR/lib/ld.so $CURDIR/opus "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/opus "$@" fi -exec $CURDIR/opus "$@" +exec "$CURDIR"/opus "$@" diff --git a/backend/go/parakeet-cpp/run.sh b/backend/go/parakeet-cpp/run.sh index be859f381..5f99c5d24 100755 --- a/backend/go/parakeet-cpp/run.sh +++ b/backend/go/parakeet-cpp/run.sh @@ -4,10 +4,10 @@ set -e CURDIR=$(dirname "$(realpath "$0")") if [ "$(uname)" = "Darwin" ]; then - export DYLD_LIBRARY_PATH="$CURDIR/lib:$CURDIR:${DYLD_LIBRARY_PATH:-}" + export DYLD_LIBRARY_PATH="$CURDIR/lib:"$CURDIR":${DYLD_LIBRARY_PATH:-}" export PARAKEET_LIBRARY="$CURDIR/lib/libparakeet.dylib" else - export LD_LIBRARY_PATH="$CURDIR/lib:$CURDIR:${LD_LIBRARY_PATH:-}" + export LD_LIBRARY_PATH="$CURDIR/lib:"$CURDIR":${LD_LIBRARY_PATH:-}" export PARAKEET_LIBRARY="$CURDIR/lib/libparakeet.so" fi diff --git a/backend/go/piper/run.sh b/backend/go/piper/run.sh index fe120ea88..6e04021e3 100755 --- a/backend/go/piper/run.sh +++ b/backend/go/piper/run.sh @@ -1,15 +1,15 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") -export ESPEAK_NG_DATA=$CURDIR/espeak-ng-data -export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH +export ESPEAK_NG_DATA="$CURDIR"/espeak-ng-data +export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" - exec $CURDIR/lib/ld.so $CURDIR/piper "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/piper "$@" fi -exec $CURDIR/piper "$@" \ No newline at end of file +exec "$CURDIR"/piper "$@" \ No newline at end of file diff --git a/backend/go/qwen3-tts-cpp/run.sh b/backend/go/qwen3-tts-cpp/run.sh index 638cf9661..2b8934d1b 100755 --- a/backend/go/qwen3-tts-cpp/run.sh +++ b/backend/go/qwen3-tts-cpp/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,20 +15,20 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/libgoqwen3ttscpp-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libgoqwen3ttscpp-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libgoqwen3ttscpp-avx.so ]; then + if [ -e "$CURDIR"/libgoqwen3ttscpp-avx.so ]; then LIBRARY="$CURDIR/libgoqwen3ttscpp-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libgoqwen3ttscpp-avx2.so ]; then + if [ -e "$CURDIR"/libgoqwen3ttscpp-avx2.so ]; then LIBRARY="$CURDIR/libgoqwen3ttscpp-avx2.so" fi fi @@ -36,22 +36,22 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/libgoqwen3ttscpp-avx512.so ]; then + if [ -e "$CURDIR"/libgoqwen3ttscpp-avx512.so ]; then LIBRARY="$CURDIR/libgoqwen3ttscpp-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export QWEN3TTS_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/qwen3-tts-cpp "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/qwen3-tts-cpp "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/qwen3-tts-cpp "$@" +exec "$CURDIR"/qwen3-tts-cpp "$@" diff --git a/backend/go/rfdetr-cpp/run.sh b/backend/go/rfdetr-cpp/run.sh index ffbd604dd..0e7775cb7 100755 --- a/backend/go/rfdetr-cpp/run.sh +++ b/backend/go/rfdetr-cpp/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,20 +15,20 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/librfdetrcpp-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/librfdetrcpp-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/librfdetrcpp-avx.so ]; then + if [ -e "$CURDIR"/librfdetrcpp-avx.so ]; then LIBRARY="$CURDIR/librfdetrcpp-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/librfdetrcpp-avx2.so ]; then + if [ -e "$CURDIR"/librfdetrcpp-avx2.so ]; then LIBRARY="$CURDIR/librfdetrcpp-avx2.so" fi fi @@ -36,22 +36,22 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/librfdetrcpp-avx512.so ]; then + if [ -e "$CURDIR"/librfdetrcpp-avx512.so ]; then LIBRARY="$CURDIR/librfdetrcpp-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export RFDETR_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/rfdetr-cpp "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/rfdetr-cpp "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/rfdetr-cpp "$@" +exec "$CURDIR"/rfdetr-cpp "$@" diff --git a/backend/go/sam3-cpp/run.sh b/backend/go/sam3-cpp/run.sh index 7bff52df6..7794facde 100755 --- a/backend/go/sam3-cpp/run.sh +++ b/backend/go/sam3-cpp/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,20 +15,20 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/libgosam3-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libgosam3-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libgosam3-avx.so ]; then + if [ -e "$CURDIR"/libgosam3-avx.so ]; then LIBRARY="$CURDIR/libgosam3-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libgosam3-avx2.so ]; then + if [ -e "$CURDIR"/libgosam3-avx2.so ]; then LIBRARY="$CURDIR/libgosam3-avx2.so" fi fi @@ -36,22 +36,22 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/libgosam3-avx512.so ]; then + if [ -e "$CURDIR"/libgosam3-avx512.so ]; then LIBRARY="$CURDIR/libgosam3-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export SAM3_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/sam3-cpp "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/sam3-cpp "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/sam3-cpp "$@" +exec "$CURDIR"/sam3-cpp "$@" diff --git a/backend/go/sherpa-onnx/run.sh b/backend/go/sherpa-onnx/run.sh index 771324326..e5e4a7c62 100755 --- a/backend/go/sherpa-onnx/run.sh +++ b/backend/go/sherpa-onnx/run.sh @@ -1,19 +1,19 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") if [ "$(uname)" = "Darwin" ]; then - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH - export SHERPA_SHIM_LIBRARY=$CURDIR/lib/libsherpa-shim.dylib - export SHERPA_ONNX_LIBRARY=$CURDIR/lib/libsherpa-onnx-c-api.dylib + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH + export SHERPA_SHIM_LIBRARY="$CURDIR"/lib/libsherpa-shim.dylib + export SHERPA_ONNX_LIBRARY="$CURDIR"/lib/libsherpa-onnx-c-api.dylib else - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" - exec $CURDIR/lib/ld.so $CURDIR/sherpa-onnx "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/sherpa-onnx "$@" fi -exec $CURDIR/sherpa-onnx "$@" +exec "$CURDIR"/sherpa-onnx "$@" diff --git a/backend/go/silero-vad/run.sh b/backend/go/silero-vad/run.sh index 72658908a..d8c343223 100755 --- a/backend/go/silero-vad/run.sh +++ b/backend/go/silero-vad/run.sh @@ -1,14 +1,14 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") -export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" - exec $CURDIR/lib/ld.so $CURDIR/silero-vad "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/silero-vad "$@" fi -exec $CURDIR/silero-vad "$@" \ No newline at end of file +exec "$CURDIR"/silero-vad "$@" \ No newline at end of file diff --git a/backend/go/stablediffusion-ggml/run.sh b/backend/go/stablediffusion-ggml/run.sh index e026b4b28..94d920490 100755 --- a/backend/go/stablediffusion-ggml/run.sh +++ b/backend/go/stablediffusion-ggml/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -20,20 +20,20 @@ if [ "$(uname)" = "Darwin" ]; then if [ ! -e "$LIBRARY" ]; then LIBRARY="$CURDIR/libgosd-fallback.so" fi - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libgosd-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libgosd-avx.so ]; then + if [ -e "$CURDIR"/libgosd-avx.so ]; then LIBRARY="$CURDIR/libgosd-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libgosd-avx2.so ]; then + if [ -e "$CURDIR"/libgosd-avx2.so ]; then LIBRARY="$CURDIR/libgosd-avx2.so" fi fi @@ -41,22 +41,22 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/libgosd-avx512.so ]; then + if [ -e "$CURDIR"/libgosd-avx512.so ]; then LIBRARY="$CURDIR/libgosd-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export SD_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/stablediffusion-ggml "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/stablediffusion-ggml "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/stablediffusion-ggml "$@" +exec "$CURDIR"/stablediffusion-ggml "$@" diff --git a/backend/go/supertonic/run.sh b/backend/go/supertonic/run.sh index 683c52ab2..5d116e834 100755 --- a/backend/go/supertonic/run.sh +++ b/backend/go/supertonic/run.sh @@ -1,21 +1,21 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") if [ "$(uname)" = "Darwin" ]; then # macOS uses dyld: there is no ld.so loader, and the search path env # var is DYLD_LIBRARY_PATH. ONNX Runtime ships as a .dylib here. - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH - export ONNXRUNTIME_LIB_PATH=$CURDIR/lib/libonnxruntime.dylib + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH + export ONNXRUNTIME_LIB_PATH="$CURDIR"/lib/libonnxruntime.dylib else - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH - export ONNXRUNTIME_LIB_PATH=$CURDIR/lib/libonnxruntime.so + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH + export ONNXRUNTIME_LIB_PATH="$CURDIR"/lib/libonnxruntime.so - if [ -f $CURDIR/lib/ld.so ]; then + if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" - exec $CURDIR/lib/ld.so $CURDIR/supertonic "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/supertonic "$@" fi fi -exec $CURDIR/supertonic "$@" +exec "$CURDIR"/supertonic "$@" diff --git a/backend/go/vibevoice-cpp/run.sh b/backend/go/vibevoice-cpp/run.sh index ec5a39c14..6ce29cb44 100755 --- a/backend/go/vibevoice-cpp/run.sh +++ b/backend/go/vibevoice-cpp/run.sh @@ -1,7 +1,7 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -14,41 +14,41 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/libgovibevoicecpp-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libgovibevoicecpp-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libgovibevoicecpp-avx.so ]; then + if [ -e "$CURDIR"/libgovibevoicecpp-avx.so ]; then LIBRARY="$CURDIR/libgovibevoicecpp-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libgovibevoicecpp-avx2.so ]; then + if [ -e "$CURDIR"/libgovibevoicecpp-avx2.so ]; then LIBRARY="$CURDIR/libgovibevoicecpp-avx2.so" fi fi if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/libgovibevoicecpp-avx512.so ]; then + if [ -e "$CURDIR"/libgovibevoicecpp-avx512.so ]; then LIBRARY="$CURDIR/libgovibevoicecpp-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export VIBEVOICECPP_LIBRARY=$LIBRARY -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/vibevoice-cpp "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/vibevoice-cpp "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/vibevoice-cpp "$@" +exec "$CURDIR"/vibevoice-cpp "$@" diff --git a/backend/go/voxtral/run.sh b/backend/go/voxtral/run.sh index 748c30341..b8be0580d 100644 --- a/backend/go/voxtral/run.sh +++ b/backend/go/voxtral/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,35 +15,35 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/libgovoxtral-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libgovoxtral-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libgovoxtral-avx.so ]; then + if [ -e "$CURDIR"/libgovoxtral-avx.so ]; then LIBRARY="$CURDIR/libgovoxtral-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libgovoxtral-avx2.so ]; then + if [ -e "$CURDIR"/libgovoxtral-avx2.so ]; then LIBRARY="$CURDIR/libgovoxtral-avx2.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export VOXTRAL_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it (Linux only) -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/voxtral "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/voxtral "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/voxtral "$@" +exec "$CURDIR"/voxtral "$@" diff --git a/backend/go/whisper/run.sh b/backend/go/whisper/run.sh index 0e2bd7eb0..444a247c7 100755 --- a/backend/go/whisper/run.sh +++ b/backend/go/whisper/run.sh @@ -2,7 +2,7 @@ set -ex # Get the absolute current dir where the script is located -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") cd / @@ -15,20 +15,20 @@ fi if [ "$(uname)" = "Darwin" ]; then # macOS: single dylib variant (Metal or Accelerate) LIBRARY="$CURDIR/libgowhisper-fallback.dylib" - export DYLD_LIBRARY_PATH=$CURDIR/lib:$DYLD_LIBRARY_PATH + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH else LIBRARY="$CURDIR/libgowhisper-fallback.so" if grep -q -e "\savx\s" /proc/cpuinfo ; then echo "CPU: AVX found OK" - if [ -e $CURDIR/libgowhisper-avx.so ]; then + if [ -e "$CURDIR"/libgowhisper-avx.so ]; then LIBRARY="$CURDIR/libgowhisper-avx.so" fi fi if grep -q -e "\savx2\s" /proc/cpuinfo ; then echo "CPU: AVX2 found OK" - if [ -e $CURDIR/libgowhisper-avx2.so ]; then + if [ -e "$CURDIR"/libgowhisper-avx2.so ]; then LIBRARY="$CURDIR/libgowhisper-avx2.so" fi fi @@ -36,22 +36,22 @@ else # Check avx 512 if grep -q -e "\savx512f\s" /proc/cpuinfo ; then echo "CPU: AVX512F found OK" - if [ -e $CURDIR/libgowhisper-avx512.so ]; then + if [ -e "$CURDIR"/libgowhisper-avx512.so ]; then LIBRARY="$CURDIR/libgowhisper-avx512.so" fi fi - export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH fi export WHISPER_LIBRARY=$LIBRARY # If there is a lib/ld.so, use it -if [ -f $CURDIR/lib/ld.so ]; then +if [ -f "$CURDIR"/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using library: $LIBRARY" - exec $CURDIR/lib/ld.so $CURDIR/whisper "$@" + exec "$CURDIR"/lib/ld.so "$CURDIR"/whisper "$@" fi echo "Using library: $LIBRARY" -exec $CURDIR/whisper "$@" \ No newline at end of file +exec "$CURDIR"/whisper "$@" \ No newline at end of file diff --git a/backend/rust/kokoros/run.sh b/backend/rust/kokoros/run.sh index bdea9f77a..b2acfe184 100755 --- a/backend/rust/kokoros/run.sh +++ b/backend/rust/kokoros/run.sh @@ -1,23 +1,23 @@ #!/bin/bash set -ex -CURDIR=$(dirname "$(realpath $0)") +CURDIR=$(dirname "$(realpath "$0")") -export LD_LIBRARY_PATH=$CURDIR/lib:${LD_LIBRARY_PATH:-} +export LD_LIBRARY_PATH="$CURDIR"/lib:${LD_LIBRARY_PATH:-} # SSL certificates for model auto-download if [ -d "$CURDIR/etc/ssl/certs" ]; then - export SSL_CERT_DIR=$CURDIR/etc/ssl/certs + export SSL_CERT_DIR="$CURDIR"/etc/ssl/certs fi # espeak-ng data directory if [ -d "$CURDIR/espeak-ng-data" ]; then - export ESPEAK_NG_DATA=$CURDIR/espeak-ng-data + export ESPEAK_NG_DATA="$CURDIR"/espeak-ng-data fi # Use bundled ld.so if present (portability) -if [ -f $CURDIR/lib/ld.so ]; then - exec $CURDIR/lib/ld.so $CURDIR/kokoros-grpc "$@" +if [ -f "$CURDIR"/lib/ld.so ]; then + exec "$CURDIR"/lib/ld.so "$CURDIR"/kokoros-grpc "$@" fi -exec $CURDIR/kokoros-grpc "$@" +exec "$CURDIR"/kokoros-grpc "$@" From 253aedff06c4e80a90a25752ea039b209183fb10 Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 01:08:09 +0200 Subject: [PATCH 05/12] chore: :arrow_up: Update CrispStrobe/CrispASR to `8f1218141b792b8868861c1af17ba1e361b05dc0` (#10502) :arrow_up: Update CrispStrobe/CrispASR Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: mudler <2420543+mudler@users.noreply.github.com> --- backend/go/crispasr/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/go/crispasr/Makefile b/backend/go/crispasr/Makefile index 1b32240e3..d6921b15a 100644 --- a/backend/go/crispasr/Makefile +++ b/backend/go/crispasr/Makefile @@ -8,7 +8,7 @@ JOBS?=$(shell nproc --ignore=1) # CrispASR version (release tag) CRISPASR_REPO?=https://github.com/CrispStrobe/CrispASR -CRISPASR_VERSION?=96b2a6ee31d30389fed8a7ef1a54239b75231ddc +CRISPASR_VERSION?=8f1218141b792b8868861c1af17ba1e361b05dc0 SO_TARGET?=libgocrispasr.so CMAKE_ARGS+=-DBUILD_SHARED_LIBS=OFF From 86677495a2294ec48a5e57eb53ee132f65e0299d Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 01:15:40 +0200 Subject: [PATCH 06/12] chore: :arrow_up: Update ggml-org/llama.cpp to `9d5d882d8cd0f0a9283d87ed5e6fe3ee0d925fb1` (#10514) :arrow_up: Update ggml-org/llama.cpp Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: mudler <2420543+mudler@users.noreply.github.com> --- backend/cpp/llama-cpp/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/cpp/llama-cpp/Makefile b/backend/cpp/llama-cpp/Makefile index b0fa0423c..b02bdac07 100644 --- a/backend/cpp/llama-cpp/Makefile +++ b/backend/cpp/llama-cpp/Makefile @@ -1,5 +1,5 @@ -LLAMA_VERSION?=8be759e6f70d629638a7eb70db3824cbdcea370b +LLAMA_VERSION?=9d5d882d8cd0f0a9283d87ed5e6fe3ee0d925fb1 LLAMA_REPO?=https://github.com/ggerganov/llama.cpp CMAKE_ARGS?= From d388f874de5e1e1cba3dd4932c6766bbe5895661 Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 01:18:41 +0200 Subject: [PATCH 07/12] feat(backends): darwin/Metal build for the privacy-filter backend (#10513) * feat(backends): darwin/Metal build for the privacy-filter backend (timeboxed try) The privacy-filter.cpp engine is already Metal-capable on Apple Silicon: it pulls ggml and never forces GGML_METAL=OFF, and ggml defaults Metal ON on Apple, so a plain Darwin build is Metal-enabled. grpc++/protobuf resolve from Homebrew via find_package(... CONFIG). It just had no darwin build path - the existing package.sh and run.sh are Linux-only and there was no make target / workflow step. Adds the bespoke darwin path, modeled on the ds4 one: - scripts/build/privacy-filter-darwin.sh: native make grpc-server, otool -L dylib bundling, create-oci-image (no Linux package.sh). - Makefile: backends/privacy-filter-darwin target (+ .NOTPARALLEL). - .github/workflows/backend_build_darwin.yml: gated build step for privacy-filter. - scripts/changed-backends.js: inferBackendPathDarwin special-case -> backend/cpp. - .github/backend-matrix.yml: includeDarwin entry (lang go, like ds4/llama-cpp). - backend/index.yaml: metal: capability + metal-privacy-filter(-development) entries. - backend/cpp/privacy-filter/run.sh: DYLD_LIBRARY_PATH branch on Darwin. Signed-off-by: Ettore Di Giacinto Assisted-by: Claude:opus-4.8 [Claude Code] * fix(privacy-filter): macOS proto include + bundle ggml dylibs Validated natively on an M4 (the build/package/load chain now works with Metal): - CMakeLists.txt: hw_grpc_proto compiles the generated proto/grpc sources but only linked the binary dir, so on macOS it could not find protobuf's headers (runtime_version.h) - Homebrew puts them under /opt/homebrew, not /usr/include. Link protobuf::libprotobuf + gRPC::grpc++ so their include dirs propagate. No-op on Linux (apt headers are already on the default search path). - privacy-filter-darwin.sh: bundle the ggml shared libs the binary @rpath-links (libggml{,-base,-cpu,-blas,-metal}); the otool -L walk only catches on-disk absolute deps and missed them. Resolved at runtime by run.sh's DYLD_LIBRARY_PATH. M4 check: arm64 grpc-server links @rpath/libggml-metal.0.dylib; with the 15 ggml dylibs + grpc/protobuf bundled, it loads clean (no dyld errors) and prints usage. Signed-off-by: Ettore Di Giacinto Assisted-by: Claude:opus-4.8 [Claude Code] --------- Signed-off-by: Ettore Di Giacinto Co-authored-by: Ettore Di Giacinto --- .github/backend-matrix.yml | 6 ++ .github/workflows/backend_build_darwin.yml | 11 +++- Makefile | 6 +- backend/cpp/privacy-filter/CMakeLists.txt | 8 +++ backend/cpp/privacy-filter/run.sh | 8 ++- backend/index.yaml | 11 ++++ scripts/build/privacy-filter-darwin.sh | 66 ++++++++++++++++++++++ scripts/changed-backends.js | 5 ++ 8 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 scripts/build/privacy-filter-darwin.sh diff --git a/.github/backend-matrix.yml b/.github/backend-matrix.yml index b66f1bbf3..6147f1250 100644 --- a/.github/backend-matrix.yml +++ b/.github/backend-matrix.yml @@ -4963,6 +4963,12 @@ includeDarwin: tag-suffix: "-metal-darwin-arm64-sam3-cpp" build-type: "metal" lang: "go" + # privacy-filter (PII/NER) is a C++/ggml backend built by a bespoke darwin + # script (make backends/privacy-filter-darwin); ggml defaults Metal ON on Apple + # so the build is Metal-enabled. lang=go drives runner/toolchain selection only. + - backend: "privacy-filter" + tag-suffix: "-metal-darwin-arm64-privacy-filter" + lang: "go" # LocalVQE has no Metal path; on Apple Silicon it builds CPU-only (GGML_METAL # OFF) but is still a native arm64 image. Uses the darwin/metal build profile. - backend: "localvqe" diff --git a/.github/workflows/backend_build_darwin.yml b/.github/workflows/backend_build_darwin.yml index 749ffd4de..e0bbdb091 100644 --- a/.github/workflows/backend_build_darwin.yml +++ b/.github/workflows/backend_build_darwin.yml @@ -228,8 +228,17 @@ jobs: run: | make backends/ds4-darwin + # privacy-filter is a C++/ggml backend like ds4 - a single grpc-server with + # otool dylib bundling - so it gets its own bespoke darwin script rather than + # the generic build-darwin-go-backend path. + - name: Build privacy-filter backend (Darwin Metal) + if: inputs.backend == 'privacy-filter' + run: | + make protogen-go + make backends/privacy-filter-darwin + - name: Build ${{ inputs.backend }}-darwin - if: inputs.backend != 'llama-cpp' && inputs.backend != 'ds4' + if: inputs.backend != 'llama-cpp' && inputs.backend != 'ds4' && inputs.backend != 'privacy-filter' run: | make protogen-go BACKEND=${{ inputs.backend }} BUILD_TYPE=${{ inputs.build-type }} USE_PIP=${{ inputs.use-pip }} make build-darwin-${{ inputs.lang }}-backend diff --git a/Makefile b/Makefile index be0711b47..b3ab4fe57 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Disable parallel execution for backend builds -.NOTPARALLEL: backends/diffusers backends/llama-cpp backends/turboquant backends/outetts backends/piper backends/stablediffusion-ggml backends/whisper backends/crispasr backends/parakeet-cpp backends/faster-whisper backends/silero-vad backends/local-store backends/huggingface backends/rfdetr backends/rfdetr-cpp backends/insightface backends/speaker-recognition backends/kitten-tts backends/kokoro backends/chatterbox backends/llama-cpp-darwin backends/neutts build-darwin-python-backend build-darwin-go-backend backends/mlx backends/diffuser-darwin backends/mlx-vlm backends/mlx-audio backends/mlx-distributed backends/stablediffusion-ggml-darwin backends/vllm backends/vllm-omni backends/sglang backends/moonshine backends/pocket-tts backends/qwen-tts backends/faster-qwen3-tts backends/qwen-asr backends/nemo backends/voxcpm backends/whisperx backends/ace-step backends/acestep-cpp backends/fish-speech backends/voxtral backends/opus backends/trl backends/llama-cpp-quantization backends/kokoros backends/sam3-cpp backends/qwen3-tts-cpp backends/omnivoice-cpp backends/vibevoice-cpp backends/localvqe backends/tinygrad backends/sherpa-onnx backends/ds4 backends/ds4-darwin backends/liquid-audio backends/supertonic backends/depth-anything-cpp backends/privacy-filter +.NOTPARALLEL: backends/diffusers backends/llama-cpp backends/turboquant backends/outetts backends/piper backends/stablediffusion-ggml backends/whisper backends/crispasr backends/parakeet-cpp backends/faster-whisper backends/silero-vad backends/local-store backends/huggingface backends/rfdetr backends/rfdetr-cpp backends/insightface backends/speaker-recognition backends/kitten-tts backends/kokoro backends/chatterbox backends/llama-cpp-darwin backends/neutts build-darwin-python-backend build-darwin-go-backend backends/mlx backends/diffuser-darwin backends/mlx-vlm backends/mlx-audio backends/mlx-distributed backends/stablediffusion-ggml-darwin backends/vllm backends/vllm-omni backends/sglang backends/moonshine backends/pocket-tts backends/qwen-tts backends/faster-qwen3-tts backends/qwen-asr backends/nemo backends/voxcpm backends/whisperx backends/ace-step backends/acestep-cpp backends/fish-speech backends/voxtral backends/opus backends/trl backends/llama-cpp-quantization backends/kokoros backends/sam3-cpp backends/qwen3-tts-cpp backends/omnivoice-cpp backends/vibevoice-cpp backends/localvqe backends/tinygrad backends/sherpa-onnx backends/ds4 backends/ds4-darwin backends/liquid-audio backends/supertonic backends/depth-anything-cpp backends/privacy-filter backends/privacy-filter-darwin GOCMD=go GOTEST=$(GOCMD) test @@ -1129,6 +1129,10 @@ backends/ds4-darwin: build bash ./scripts/build/ds4-darwin.sh ./local-ai backends install "ocifile://$(abspath ./backend-images/ds4.tar)" +backends/privacy-filter-darwin: build + bash ./scripts/build/privacy-filter-darwin.sh + ./local-ai backends install "ocifile://$(abspath ./backend-images/privacy-filter.tar)" + build-darwin-python-backend: build bash ./scripts/build/python-darwin.sh diff --git a/backend/cpp/privacy-filter/CMakeLists.txt b/backend/cpp/privacy-filter/CMakeLists.txt index b8580d1d4..f9ee78328 100644 --- a/backend/cpp/privacy-filter/CMakeLists.txt +++ b/backend/cpp/privacy-filter/CMakeLists.txt @@ -51,6 +51,14 @@ add_library(hw_grpc_proto STATIC ${HW_GRPC_SRCS} ${HW_GRPC_HDRS} ${HW_PROTO_SRCS} ${HW_PROTO_HDRS}) target_include_directories(hw_grpc_proto PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +# The generated proto/grpc sources include protobuf and grpc++ headers, so this +# library must see their include dirs. Linking the imported targets propagates +# them. On Linux the apt headers live in /usr/include (default search path) so +# this was a no-op; on macOS the Homebrew headers are under /opt/homebrew and +# would otherwise be missed (runtime_version.h not found). +target_link_libraries(hw_grpc_proto PUBLIC + protobuf::libprotobuf + gRPC::grpc++) # Build only the pf static lib (+ ggml) from the engine tree — no CLI/bench/tests. # PF_VULKAN is honored when passed on the cmake command line (it lands in the diff --git a/backend/cpp/privacy-filter/run.sh b/backend/cpp/privacy-filter/run.sh index 489b64580..0f4f22270 100755 --- a/backend/cpp/privacy-filter/run.sh +++ b/backend/cpp/privacy-filter/run.sh @@ -2,7 +2,13 @@ # Entry point for the privacy-filter backend image / BACKEND_BINARY mode. set -e CURDIR=$(dirname "$(realpath "$0")") -export LD_LIBRARY_PATH="$CURDIR/lib:$LD_LIBRARY_PATH" +# macOS has no bundled ld.so; the darwin package ships only dylibs under lib/, +# resolved via DYLD_LIBRARY_PATH (the ld.so branch below is skipped there). +if [ "$(uname)" = "Darwin" ]; then + export DYLD_LIBRARY_PATH="$CURDIR/lib:$DYLD_LIBRARY_PATH" +else + export LD_LIBRARY_PATH="$CURDIR/lib:$LD_LIBRARY_PATH" +fi if [ -f "$CURDIR/lib/ld.so" ]; then exec "$CURDIR/lib/ld.so" "$CURDIR/grpc-server" "$@" fi diff --git a/backend/index.yaml b/backend/index.yaml index a7399e20d..2841d0f79 100644 --- a/backend/index.yaml +++ b/backend/index.yaml @@ -1095,6 +1095,7 @@ amd: "vulkan-privacy-filter" intel: "vulkan-privacy-filter" vulkan: "vulkan-privacy-filter" + metal: "metal-privacy-filter" - &faster-whisper icon: https://avatars.githubusercontent.com/u/1520500?s=200&v=4 description: | @@ -2937,6 +2938,16 @@ uri: "quay.io/go-skynet/local-ai-backends:master-gpu-vulkan-privacy-filter" mirrors: - localai/localai-backends:master-gpu-vulkan-privacy-filter +- !!merge <<: *privacyfilter + name: "metal-privacy-filter" + uri: "quay.io/go-skynet/local-ai-backends:latest-metal-darwin-arm64-privacy-filter" + mirrors: + - localai/localai-backends:latest-metal-darwin-arm64-privacy-filter +- !!merge <<: *privacyfilter + name: "metal-privacy-filter-development" + uri: "quay.io/go-skynet/local-ai-backends:master-metal-darwin-arm64-privacy-filter" + mirrors: + - localai/localai-backends:master-metal-darwin-arm64-privacy-filter - !!merge <<: *privacyfilter name: "cuda13-privacy-filter" uri: "quay.io/go-skynet/local-ai-backends:latest-gpu-nvidia-cuda-13-privacy-filter" diff --git a/scripts/build/privacy-filter-darwin.sh b/scripts/build/privacy-filter-darwin.sh new file mode 100644 index 000000000..aca901822 --- /dev/null +++ b/scripts/build/privacy-filter-darwin.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Darwin/Metal build for the privacy-filter backend. Mirrors ds4-darwin.sh: +# native make of the single grpc-server, otool -L dylib bundling, then assemble +# an OCI tar that `local-ai backends install` can consume. +# +# privacy-filter.cpp pulls ggml, which defaults GGML_METAL=ON on Apple - the +# engine's CMake never forces it off, so a plain Darwin build is Metal-enabled. +# grpc++/protobuf are resolved from Homebrew via find_package(... CONFIG). +set -ex + +IMAGE_NAME="${IMAGE_NAME:-localai/privacy-filter-darwin}" + +pushd backend/cpp/privacy-filter +make grpc-server +popd + +mkdir -p build/darwin +mkdir -p build/darwin/lib +mkdir -p backend-images + +cp -rf backend/cpp/privacy-filter/grpc-server build/darwin/ +cp -rf backend/cpp/privacy-filter/run.sh build/darwin/ + +# Apple Silicon: pick up Homebrew-installed protobuf utf8_validity if present +# (same as ds4-darwin.sh - it is a transitive dep otool may not surface). +if [[ "$(uname -s)" == "Darwin" && "$(uname -m)" == "arm64" ]]; then + ADDITIONAL_LIBS=${ADDITIONAL_LIBS:-$(ls /opt/homebrew/Cellar/protobuf/**/lib/libutf8_validity*.dylib 2>/dev/null)} +else + ADDITIONAL_LIBS=${ADDITIONAL_LIBS:-""} +fi +for file in $ADDITIONAL_LIBS; do + cp -rfv "$file" build/darwin/lib +done + +# Bundle the ggml shared libs the binary @rpath-links (libggml, -cpu, -blas, +# -metal). The engine builds ggml shared, scattered under the build tree; flatten +# them (with their version symlinks) into lib/, resolved at runtime by leaf name +# via run.sh's DYLD_LIBRARY_PATH=lib. Without this the packaged binary can't find +# libggml*.dylib once the build dir is gone. +GGML_SRC="backend/cpp/privacy-filter/build/privacy-filter.cpp/ggml/src" +find "$GGML_SRC" -name 'libggml*.dylib' -exec cp -a {} build/darwin/lib/ \; + +# Walk dylibs via otool -L and bundle anything that isn't a system framework. +for file in build/darwin/grpc-server; do + LIBS="$(otool -L "$file" | awk 'NR > 1 { system("echo " $1) } ' | xargs echo)" + for lib in $LIBS; do + if [[ "$lib" == *.dylib ]] && [[ -e "$lib" ]]; then + cp -rvf "$lib" build/darwin/lib + fi + done +done + +echo "Bundled libraries:" +ls -la build/darwin/lib + +# Build an OCI image tar (with manifest.json) that `local-ai backends install` +# can consume - mirrors ds4-darwin.sh. +PLATFORMARCH="${PLATFORMARCH:-darwin/arm64}" + +./local-ai util create-oci-image \ + build/darwin/. \ + --output ./backend-images/privacy-filter.tar \ + --image-name "$IMAGE_NAME" \ + --platform "$PLATFORMARCH" + +rm -rf build/darwin diff --git a/scripts/changed-backends.js b/scripts/changed-backends.js index 5690e00f5..758cdb869 100644 --- a/scripts/changed-backends.js +++ b/scripts/changed-backends.js @@ -71,6 +71,11 @@ function inferBackendPathDarwin(item) { if (item.backend === "ds4") { return `backend/cpp/ds4/`; } + // privacy-filter is C++ too (built via `make backends/privacy-filter-darwin`); + // same lang=go-for-runner convention, source under backend/cpp. + if (item.backend === "privacy-filter") { + return `backend/cpp/privacy-filter/`; + } if (!item.lang) { return `backend/python/${item.backend}/`; } From 114eeaae81d7077ff8cbc2a29c48475d55c35708 Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 07:42:45 +0200 Subject: [PATCH 08/12] feat(backends): make PreferDevelopmentBackends install the development image as primary (#10520) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When LOCALAI_PREFER_DEV_BACKENDS is set, install the -development image as the primary backend URI (keeping the released image reachable as the first fallback), instead of only reaching development as a download fallback when the released image is missing. This lets an operator force backends built from the development branch — e.g. to pick up a fix already on master before a release. Threads PreferDevelopmentBackends through SystemState so InstallBackend can see it, and reuses the same development-URI convention as the existing failure-path fallback (released tag -> branch tag + dev suffix). The unexported developmentURI helper is covered by a Ginkgo spec. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ettore Di Giacinto Co-authored-by: Ettore Di Giacinto --- core/cli/run.go | 1 + core/gallery/backends.go | 40 ++++++++++++++++++++++++---- core/gallery/backends_devuri_test.go | 26 ++++++++++++++++++ pkg/system/state.go | 10 +++++++ 4 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 core/gallery/backends_devuri_test.go diff --git a/core/cli/run.go b/core/cli/run.go index fd7ba8cd9..0302b5706 100644 --- a/core/cli/run.go +++ b/core/cli/run.go @@ -203,6 +203,7 @@ func (r *RunCMD) Run(ctx *cliContext.Context) error { system.WithBackendImagesReleaseTag(r.BackendImagesReleaseTag), system.WithBackendImagesBranchTag(r.BackendImagesBranchTag), system.WithBackendDevSuffix(r.BackendDevSuffix), + system.WithPreferDevelopmentBackends(r.PreferDevelopmentBackends), ) if err != nil { return err diff --git a/core/gallery/backends.go b/core/gallery/backends.go index 98b1254ef..ab324addf 100644 --- a/core/gallery/backends.go +++ b/core/gallery/backends.go @@ -59,6 +59,22 @@ func getFallbackTagValues(systemState *system.SystemState) (latestTag, masterTag return latestTag, masterTag, devSuffix } +// developmentURI returns the development image URI for a released backend URI by +// swapping the released tag for the branch tag (e.g. +// latest-metal-darwin-arm64-llama-cpp -> master-metal-darwin-arm64-llama-cpp). +// The branch image tracks development. ok is false when uri has no released tag +// to swap or already uses the branch tag. +func developmentURI(uri, latestTag, masterTag string) (string, bool) { + if strings.Contains(uri, masterTag+"-") { + return "", false + } + branchURI := strings.Replace(uri, latestTag+"-", masterTag+"-", 1) + if branchURI == uri { + return "", false + } + return branchURI, true +} + // backendCandidate represents an installed concrete backend option for a given alias type backendCandidate struct { name string @@ -295,15 +311,28 @@ func InstallBackend(ctx context.Context, systemState *system.SystemState, modelL return fmt.Errorf("backend %q: %w", config.Name, optsErr) } - uri := downloader.URI(config.URI) + // PreferDevelopmentBackends installs the development image as the primary URI, + // keeping the released image reachable as the first fallback — instead of only + // reaching development when the released image is missing. + primaryURI := string(config.URI) + mirrors := config.Mirrors + if systemState.PreferDevelopmentBackends { + if devURI, ok := developmentURI(string(config.URI), latestTag, masterTag); ok { + xlog.Info("PreferDevelopmentBackends: installing development image first", "development", devURI, "released", config.URI) + primaryURI = devURI + mirrors = append([]string{string(config.URI)}, config.Mirrors...) + } + } + + uri := downloader.URI(primaryURI) // Check if it is a directory if uri.LooksLikeDir() { // It is a directory, we just copy it over in the backend folder - if err := cp.Copy(config.URI, backendPath); err != nil { + if err := cp.Copy(string(uri), backendPath); err != nil { return fmt.Errorf("failed copying: %w", err) } } else { - xlog.Debug("Downloading backend", "uri", config.URI, "backendPath", backendPath) + xlog.Debug("Downloading backend", "uri", primaryURI, "backendPath", backendPath) if err := uri.DownloadFileWithContext(ctx, backendPath, config.SHA256, 1, 1, downloadStatus, downloadOpts...); err != nil { xlog.Debug("Backend download failed, trying fallback", "backendPath", backendPath, "error", err) @@ -316,8 +345,9 @@ func InstallBackend(ctx context.Context, systemState *system.SystemState, modelL } success := false - // Try to download from mirrors - for _, mirror := range config.Mirrors { + // Try to download from mirrors (when development is preferred, the + // released image is prepended here as the first fallback). + for _, mirror := range mirrors { // Check for cancellation before trying next mirror select { case <-ctx.Done(): diff --git a/core/gallery/backends_devuri_test.go b/core/gallery/backends_devuri_test.go new file mode 100644 index 000000000..f82b318eb --- /dev/null +++ b/core/gallery/backends_devuri_test.go @@ -0,0 +1,26 @@ +package gallery + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("developmentURI", func() { + const latest, master = "latest", "master" + + It("rewrites a released image to its branch (development) image", func() { + got, ok := developmentURI("quay.io/go-skynet/local-ai-backends:latest-metal-darwin-arm64-llama-cpp", latest, master) + Expect(ok).To(BeTrue()) + Expect(got).To(Equal("quay.io/go-skynet/local-ai-backends:master-metal-darwin-arm64-llama-cpp")) + }) + + It("leaves an image already on the branch tag untouched", func() { + _, ok := developmentURI("quay.io/go-skynet/local-ai-backends:master-metal-darwin-arm64-llama-cpp", latest, master) + Expect(ok).To(BeFalse()) + }) + + It("returns ok=false when there is no released tag to swap", func() { + _, ok := developmentURI("oci://localhost/custom-backend:edge", latest, master) + Expect(ok).To(BeFalse()) + }) +}) diff --git a/pkg/system/state.go b/pkg/system/state.go index 2d9afcf04..2ad52b7d3 100644 --- a/pkg/system/state.go +++ b/pkg/system/state.go @@ -26,6 +26,10 @@ type SystemState struct { BackendImagesReleaseTag string BackendImagesBranchTag string BackendDevSuffix string + // PreferDevelopmentBackends installs the development image as the primary + // backend URI (the released image becomes a fallback) rather than only using + // development as a download fallback when the released image is missing. + PreferDevelopmentBackends bool } type SystemStateOptions func(*SystemState) @@ -66,6 +70,12 @@ func WithBackendDevSuffix(suffix string) SystemStateOptions { } } +func WithPreferDevelopmentBackends(prefer bool) SystemStateOptions { + return func(s *SystemState) { + s.PreferDevelopmentBackends = prefer + } +} + func GetSystemState(opts ...SystemStateOptions) (*SystemState, error) { state := &SystemState{} for _, opt := range opts { From 11b062f8f49b83bc25571f6eb41a3bc11816a6bc Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 07:43:29 +0200 Subject: [PATCH 09/12] chore(model gallery): :robot: add 1 new models via gallery agent (#10521) chore(model gallery): :robot: add new models via gallery agent Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: mudler <2420543+mudler@users.noreply.github.com> --- gallery/index.yaml | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/gallery/index.yaml b/gallery/index.yaml index 25a6e781d..15c97b190 100644 --- a/gallery/index.yaml +++ b/gallery/index.yaml @@ -1,4 +1,58 @@ --- +- name: "ornith-1.0-35b" + url: "github:mudler/LocalAI/gallery/virtual.yaml@master" + urls: + - https://huggingface.co/deepreinforce-ai/Ornith-1.0-35B-GGUF + description: | + [](https://deep-reinforce.com/ornith.html) + + # Ornith-1.0-35B-GGUF + + Aloha! 🌺 Today, we are releasing Ornith-1.0, a self-improving family of open-source models for agentic coding. + + Highlights: + + - **State-of-the-Art Coding Agents**: Available in 9B-Dense, 31B-Dense, 35B-MoE, and 397B-MoE (post-trained on top of Gemma 4 and Qwen 3.5), achieving state-of-the-art performance among open-source models of comparable size on coding benchmarks such as Terminal-Bench 2.1, SWE-Bench, NL2Repo and OpenClaw. + - **Self-Improving Training Framework**: Ornith-1.0 employs RL to learn to generate not only solution rollouts, but also the scallfold that drive those rollouts. By jointly optimizing the scaffold and the resulting solution, the model discovers better search trajectories and generates higher-quality solutions. + - **Licence**: MIT licensed, globally accessible, and free from regional limitations. + + ## Ornith 1.0 35B + + This model card documents **Ornith-1.0-35B**, the lightweight member of the Ornith family, designed for efficient single-GPU deployment. + + ### Benchmarks + + Ornith-1.0-35B + Qwen3.5-35B + Qwen3.6-35B + Gemma4-31B + Qwen3.5-397B + + Agentic Coding + + ... + license: "mit" + tags: + - llm + - gguf + overrides: + backend: llama-cpp + function: + automatic_tool_parsing_fallback: true + grammar: + disable: true + known_usecases: + - chat + options: + - use_jinja:true + parameters: + model: llama-cpp/models/Ornith-1.0-35B-GGUF/ornith-1.0-35b-Q4_K_M.gguf + template: + use_tokenizer_template: true + files: + - filename: llama-cpp/models/Ornith-1.0-35B-GGUF/ornith-1.0-35b-Q4_K_M.gguf + sha256: ff25291b2599fb927a835e624d2b3540106af61761c3fa57ac4264046dbec002 + uri: https://huggingface.co/deepreinforce-ai/Ornith-1.0-35B-GGUF/resolve/main/ornith-1.0-35b-Q4_K_M.gguf - name: "gemmable-4-12b-mtp" url: "github:mudler/LocalAI/gallery/virtual.yaml@master" urls: From f58dcefed42e45553131ce2a1db3ed467dfd464c Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 08:48:27 +0200 Subject: [PATCH 10/12] fix(backends): ship the package/ dir for darwin go backend images (#10522) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(backends): ship the package/ dir for darwin go backends golang-darwin.sh packaged the whole backend source/build dir as the OCI image (backend/go/$BACKEND/.), so the runtime dylibs ended up under package/lib and backend-assets/lib while run.sh looks in $CURDIR/lib. As a result a backend like sherpa-onnx could not dlopen its libsherpa-shim.dylib at runtime and exited immediately (the model then 500s with "grpc service not ready"); it started fine only when run from inside package/. Ship package/. instead — the self-contained run.sh + binary + lib/ bundle — matching the Linux Dockerfile.golang (`COPY .../package/. ./`). Backends that don't assemble a package/ fall back to the backend dir, and the binary-existence guard now checks the directory actually shipped. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ettore Di Giacinto Co-authored-by: Ettore Di Giacinto --- scripts/build/golang-darwin.sh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/scripts/build/golang-darwin.sh b/scripts/build/golang-darwin.sh index 02e75f736..fddd4bc4f 100644 --- a/scripts/build/golang-darwin.sh +++ b/scripts/build/golang-darwin.sh @@ -22,8 +22,20 @@ if [ -f "${BACKEND_DIR}/run.sh" ]; then RUN_BINARY=$(grep -oE '\$CURDIR/[A-Za-z0-9._-]+' "${BACKEND_DIR}/run.sh" | grep -v 'ld\.so' | tail -1 | sed 's|\$CURDIR/||') fi RUN_BINARY="${RUN_BINARY:-${BACKEND}}" -if [ ! -x "${BACKEND_DIR}/${RUN_BINARY}" ]; then - echo "ERROR: ${BACKEND_DIR}/${RUN_BINARY} not found after build; refusing to package a broken backend image (see issue #10267)." >&2 + +# Ship the self-contained package/ dir (run.sh + binary + lib/), matching the +# Linux Dockerfile.golang (`COPY .../package/. ./`). Packaging the whole backend +# dir instead left the runtime libraries under package/lib while run.sh looks in +# $CURDIR/lib, so backends such as sherpa-onnx could not dlopen their libs at +# runtime (they started fine only when run from inside package/). Backends that +# don't assemble a package/ fall back to the backend dir. +OCI_ROOT="${BACKEND_DIR}" +if [ -d "${BACKEND_DIR}/package" ]; then + OCI_ROOT="${BACKEND_DIR}/package" +fi + +if [ ! -x "${OCI_ROOT}/${RUN_BINARY}" ]; then + echo "ERROR: ${OCI_ROOT}/${RUN_BINARY} not found after build; refusing to package a broken backend image (see issue #10267)." >&2 exit 1 fi @@ -31,7 +43,7 @@ PLATFORMARCH="${PLATFORMARCH:-darwin/arm64}" IMAGE_NAME="${IMAGE_NAME:-localai/${BACKEND}-darwin}" ./local-ai util create-oci-image \ - backend/go/${BACKEND}/. \ + "${OCI_ROOT}/." \ --output ./backend-images/${BACKEND}.tar \ --image-name $IMAGE_NAME \ --platform $PLATFORMARCH From 6afe127cd48feb89646de6fc4425ab127f47b5d3 Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 11:19:50 +0200 Subject: [PATCH 11/12] fix(backends): make the opus backend build and package on macOS/Darwin (#10523) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The opus Go backend (WebRTC audio codec) never built on macOS, so the published master-metal-darwin-arm64-opus image shipped source only — no opus binary and no libopusshim — because every step assumed Linux. - Makefile: hardcoded libopusshim.so with no OS handling. Mirror sherpa-onnx: SHIM_EXT=so / dylib on Darwin and build libopusshim.$(SHIM_EXT). On Darwin link the shim with -undefined dynamic_lookup so it resolves opus_encoder_ctl from the already globally-loaded libopus (codec.go dlopens it RTLD_GLOBAL first) instead of baking an absolute Homebrew path into the dylib, keeping the packaged shim relocatable. - run.sh: hardcoded LD_LIBRARY_PATH + libopusshim.so even on macOS. Add a Darwin branch exporting DYLD_LIBRARY_PATH and the .dylib shim, like sherpa-onnx/run.sh. - package.sh: bundle libopusshim.$(SHIM_EXT) and libopus*.dylib (not just .so) into package/lib so the OCI image (which ships package/.) is self-contained on a runtime with no Homebrew; add a Darwin arch branch so it doesn't warn/skip. - backend_build_darwin.yml: install + link opus and pkg-config via brew so the Makefile's `pkg-config opus` resolves on the macOS runner, and cache opus' Cellar dir. Go code is unchanged; darwin build is validated in CI. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ettore Di Giacinto Co-authored-by: Ettore Di Giacinto --- .github/workflows/backend_build_darwin.yml | 11 +++++++-- backend/go/opus/Makefile | 28 ++++++++++++++++++---- backend/go/opus/package.sh | 20 ++++++++++++---- backend/go/opus/run.sh | 9 +++++-- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/.github/workflows/backend_build_darwin.yml b/.github/workflows/backend_build_darwin.yml index e0bbdb091..c0ded5b85 100644 --- a/.github/workflows/backend_build_darwin.yml +++ b/.github/workflows/backend_build_darwin.yml @@ -99,6 +99,7 @@ jobs: /opt/homebrew/Cellar/xxhash /opt/homebrew/Cellar/zstd /opt/homebrew/Cellar/nlohmann-json + /opt/homebrew/Cellar/opus key: brew-${{ runner.os }}-${{ runner.arch }}-v1-${{ hashFiles('.github/workflows/backend_build_darwin.yml') }} - name: Dependencies @@ -113,7 +114,12 @@ jobs: # nlohmann-json is header-only and required by the ds4 backend # (dsml_renderer.cpp includes ); on Linux it comes # from the apt-installed nlohmann-json3-dev in the build image. - brew install protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd nlohmann-json + # opus + pkg-config are required by the opus go backend: its + # Makefile/package.sh call `pkg-config --cflags/--libs opus` to build + # libopusshim.dylib and to locate libopus.dylib for bundling. brew's + # pkg-config defaults its search path to the Homebrew prefix so the + # opus.pc is found. + brew install protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd nlohmann-json opus pkg-config # Force-reinstall ccache so brew re-validates its full runtime-dep # closure on every run. This is the durable fix: when the upstream # ccache formula gains a new transitive dep (as it has multiple times @@ -132,7 +138,7 @@ jobs: # and decides "already installed" without re-linking, so on a cache- # hit run the formulas aren't on PATH. Force-link them; --overwrite # tolerates pre-existing symlinks from earlier installs. - brew link --overwrite protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd nlohmann-json 2>/dev/null || true + brew link --overwrite protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd nlohmann-json opus pkg-config 2>/dev/null || true - name: Save Homebrew cache if: github.event_name != 'pull_request' && steps.brew-cache.outputs.cache-hit != 'true' @@ -153,6 +159,7 @@ jobs: /opt/homebrew/Cellar/xxhash /opt/homebrew/Cellar/zstd /opt/homebrew/Cellar/nlohmann-json + /opt/homebrew/Cellar/opus key: brew-${{ runner.os }}-${{ runner.arch }}-v1-${{ hashFiles('.github/workflows/backend_build_darwin.yml') }} # ---- ccache for llama.cpp CMake builds ---- diff --git a/backend/go/opus/Makefile b/backend/go/opus/Makefile index 028b16bc5..49083b3dc 100644 --- a/backend/go/opus/Makefile +++ b/backend/go/opus/Makefile @@ -1,13 +1,30 @@ GOCMD?=go GO_TAGS?= +# The opus shim is a small C wrapper around libopus' variadic +# opus_encoder_ctl (see csrc/opus_shim.c). It is built as a shared library +# and dlopen'd at runtime by the Go backend (codec.go). The extension is +# OS-specific: Linux uses .so, macOS uses .dylib. OS is exported by the root +# Makefile (`export OS := $(shell uname -s)`). +SHIM_EXT=so + OPUS_CFLAGS := $(shell pkg-config --cflags opus) OPUS_LIBS := $(shell pkg-config --libs opus) +SHIM_LDFLAGS := $(OPUS_LIBS) -libopusshim.so: csrc/opus_shim.c - $(CC) -shared -fPIC -o $@ $< $(OPUS_CFLAGS) $(OPUS_LIBS) +ifeq ($(OS),Darwin) + SHIM_EXT=dylib + # Resolve libopus symbols lazily from the already globally-loaded + # libopus (codec.go dlopens it RTLD_GLOBAL before the shim) rather than + # recording an absolute Homebrew path in the dylib. This keeps the + # packaged shim relocatable on machines that have no Homebrew. + SHIM_LDFLAGS := -undefined dynamic_lookup +endif -opus: libopusshim.so +libopusshim.$(SHIM_EXT): csrc/opus_shim.c + $(CC) -shared -fPIC -o $@ $< $(OPUS_CFLAGS) $(SHIM_LDFLAGS) + +opus: libopusshim.$(SHIM_EXT) $(GOCMD) build -tags "$(GO_TAGS)" -o opus ./ package: opus @@ -16,4 +33,7 @@ package: opus build: package clean: - rm -f opus libopusshim.so + rm -f opus libopusshim.$(SHIM_EXT) + rm -rf package + +.PHONY: build package clean diff --git a/backend/go/opus/package.sh b/backend/go/opus/package.sh index a55834f3e..1e1aaeabf 100644 --- a/backend/go/opus/package.sh +++ b/backend/go/opus/package.sh @@ -8,13 +8,23 @@ mkdir -p $CURDIR/package/lib cp -avf $CURDIR/opus $CURDIR/package/ cp -avf $CURDIR/run.sh $CURDIR/package/ -# Copy the opus shim library -cp -avf $CURDIR/libopusshim.so $CURDIR/package/lib/ +# The shim extension is OS-specific (.so on Linux, .dylib on macOS). +SHIM_EXT=so +if [ "$(uname)" = "Darwin" ]; then + SHIM_EXT=dylib +fi -# Copy system libopus +# Copy the opus shim library +cp -avf $CURDIR/libopusshim.$SHIM_EXT $CURDIR/package/lib/ + +# Copy system libopus so the backend is self-contained: the runtime base +# image has neither libopus-dev (Linux) nor Homebrew (macOS), so codec.go's +# dlopen would otherwise fail. Both name patterns are attempted; only the +# host's matching one exists. if command -v pkg-config >/dev/null 2>&1 && pkg-config --exists opus; then LIBOPUS_DIR=$(pkg-config --variable=libdir opus) - cp -avfL $LIBOPUS_DIR/libopus.so* $CURDIR/package/lib/ 2>/dev/null || true + cp -avf $LIBOPUS_DIR/libopus.so* $CURDIR/package/lib/ 2>/dev/null || true + cp -avf $LIBOPUS_DIR/libopus*.dylib $CURDIR/package/lib/ 2>/dev/null || true fi # Detect architecture and copy appropriate libraries @@ -38,6 +48,8 @@ elif [ -f "/lib/ld-linux-aarch64.so.1" ]; then cp -arfLv /lib/aarch64-linux-gnu/libdl.so.2 $CURDIR/package/lib/libdl.so.2 cp -arfLv /lib/aarch64-linux-gnu/librt.so.1 $CURDIR/package/lib/librt.so.1 cp -arfLv /lib/aarch64-linux-gnu/libpthread.so.0 $CURDIR/package/lib/libpthread.so.0 +elif [ "$(uname -s)" = "Darwin" ]; then + echo "Detected Darwin — system libraries linked dynamically, no bundled loader needed" else echo "Warning: Could not detect architecture for system library bundling" fi diff --git a/backend/go/opus/run.sh b/backend/go/opus/run.sh index 1a54b0c40..d2773fd28 100644 --- a/backend/go/opus/run.sh +++ b/backend/go/opus/run.sh @@ -3,8 +3,13 @@ set -ex CURDIR=$(dirname "$(realpath "$0")") -export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH -export OPUS_SHIM_LIBRARY="$CURDIR"/lib/libopusshim.so +if [ "$(uname)" = "Darwin" ]; then + export DYLD_LIBRARY_PATH="$CURDIR"/lib:$DYLD_LIBRARY_PATH + export OPUS_SHIM_LIBRARY="$CURDIR"/lib/libopusshim.dylib +else + export LD_LIBRARY_PATH="$CURDIR"/lib:$LD_LIBRARY_PATH + export OPUS_SHIM_LIBRARY="$CURDIR"/lib/libopusshim.so +fi # If there is a lib/ld.so, use it if [ -f "$CURDIR"/lib/ld.so ]; then From 5b3572f8b82ade2866d50f7a7cc310d1195ccfbe Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Fri, 26 Jun 2026 12:45:51 +0200 Subject: [PATCH 12/12] feat(macos): sign and notarize the DMG, app, and server binary (#10510) Produce a Gatekeeper-clean macOS distribution with no user workaround: - Launcher DMG + the LocalAI.app inside it are built via fyne, codesigned with the Developer ID under the hardened runtime, then the DMG is signed, notarized (notarytool) and stapled. Replaces macos-dmg-creator (which had no signing hook) with fyne package + hdiutil so we control the .app before packaging. - The bare local-ai darwin server binary is signed + notarized via GoReleaser's native notarize block (quill backend, runs on Linux). - All signing is gated on secrets being present, so forks/PRs/local builds stay unsigned and green (contrib/macos/sign-and-notarize.sh no-ops). - Add hardened-runtime entitlements and FyneApp.toml for deterministic packaging; update macOS install docs to drop the quarantine workaround. Assisted-by: Claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto Co-authored-by: Ettore Di Giacinto --- .github/workflows/release.yaml | 21 ++++++-- .gitignore | 3 ++ .goreleaser.yaml | 19 ++++++- Makefile | 35 +++++++++--- cmd/launcher/FyneApp.toml | 8 +++ contrib/macos/Launcher.entitlements | 14 +++++ contrib/macos/sign-and-notarize.sh | 84 +++++++++++++++++++++++++++++ docs/content/installation/macos.md | 15 +++--- 8 files changed, 181 insertions(+), 18 deletions(-) create mode 100644 cmd/launcher/FyneApp.toml create mode 100644 contrib/macos/Launcher.entitlements create mode 100755 contrib/macos/sign-and-notarize.sh diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 614c1de3e..b1b585c4b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -24,6 +24,11 @@ jobs: args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MACOS_SIGN_P12: ${{ secrets.MACOS_CERTIFICATE }} + MACOS_SIGN_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PWD }} + MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} + MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} + MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }} launcher-build-darwin: runs-on: macos-latest steps: @@ -35,9 +40,19 @@ jobs: uses: actions/setup-go@v5 with: go-version: 1.23 - - name: Build launcher for macOS ARM64 - run: | - make build-launcher-darwin + - name: Import signing certificate + env: + MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }} + MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }} + MACOS_CI_KEYCHAIN_PWD: ${{ secrets.MACOS_CI_KEYCHAIN_PWD }} + run: bash contrib/macos/sign-and-notarize.sh import-cert + - name: Build, sign and notarize the DMG + env: + MACOS_SIGN_IDENTITY: ${{ secrets.MACOS_SIGN_IDENTITY }} + MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} + MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} + MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }} + run: make release-launcher-darwin - name: Upload DMG to Release uses: softprops/action-gh-release@v3 with: diff --git a/.gitignore b/.gitignore index 177c79cba..91582c006 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,6 @@ core/http/react-ui/test-results/ # SDD / brainstorm scratch (agent-driven development) .superpowers/ + +# Local Apple signing material (never commit) +.certs/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 71c9c96e4..88d6e9ecd 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -9,7 +9,8 @@ source: enabled: true name_template: '{{ .ProjectName }}-{{ .Tag }}-source' builds: - - main: ./cmd/local-ai + - id: local-ai + main: ./cmd/local-ai env: - CGO_ENABLED=0 ldflags: @@ -35,3 +36,19 @@ snapshot: version_template: "{{ .Tag }}-next" changelog: use: github-native +# Sign + notarize the macOS server binary via the quill backend (runs on Linux, +# no macOS runner needed). Disabled automatically when MACOS_SIGN_P12 is unset +# (forks / PRs), so those builds stay unsigned and green. +notarize: + macos: + - enabled: '{{ isEnvSet "MACOS_SIGN_P12" }}' + ids: + - local-ai + sign: + certificate: "{{.Env.MACOS_SIGN_P12}}" + password: "{{.Env.MACOS_SIGN_PASSWORD}}" + notarize: + issuer_id: "{{.Env.MACOS_NOTARY_ISSUER_ID}}" + key_id: "{{.Env.MACOS_NOTARY_KEY_ID}}" + key: "{{.Env.MACOS_NOTARY_KEY}}" + wait: true diff --git a/Makefile b/Makefile index b3ab4fe57..600f6cbbe 100644 --- a/Makefile +++ b/Makefile @@ -1453,13 +1453,32 @@ docs: docs/static/gallery.html ######################################################## ## fyne cross-platform build -build-launcher-darwin: build-launcher - go run github.com/tiagomelo/macos-dmg-creator/cmd/createdmg@latest \ - --appName "LocalAI" \ - --appBinaryPath "$(LAUNCHER_BINARY_NAME)" \ - --bundleIdentifier "com.localai.launcher" \ - --iconPath "core/http/static/logo.png" \ - --outputDir "dist/" +# Build LocalAI.app from the launcher via fyne (metadata read from cmd/launcher/FyneApp.toml). +# Signing happens via contrib/macos/sign-and-notarize.sh, which is a no-op when the signing +# secrets are unset, so unsigned local/fork builds keep working. +build-launcher-darwin: + rm -rf dist/LocalAI.app cmd/launcher/LocalAI.app + mkdir -p dist + cd cmd/launcher && go run fyne.io/tools/cmd/fyne@latest package -os darwin -icon ../../core/http/static/logo.png --executable $(LAUNCHER_BINARY_NAME) + mv cmd/launcher/LocalAI.app dist/LocalAI.app + bash contrib/macos/sign-and-notarize.sh sign dist/LocalAI.app + +# Wrap the (signed) app into a drag-to-Applications DMG via hdiutil, then sign the DMG. +dmg-launcher-darwin: build-launcher-darwin + rm -rf dist/dmg dist/LocalAI.dmg + mkdir -p dist/dmg + cp -R dist/LocalAI.app dist/dmg/LocalAI.app + ln -s /Applications dist/dmg/Applications + hdiutil create -volname "LocalAI" -srcfolder dist/dmg -ov -format UDZO dist/LocalAI.dmg + bash contrib/macos/sign-and-notarize.sh sign dist/LocalAI.dmg + +# Submit the DMG to Apple notarization and staple the ticket (no-op without notary secrets). +notarize-launcher-darwin: dmg-launcher-darwin + bash contrib/macos/sign-and-notarize.sh notarize dist/LocalAI.dmg + +# Single entrypoint for CI: build -> sign app -> dmg -> sign dmg -> notarize -> staple. +release-launcher-darwin: notarize-launcher-darwin + @echo "dist/LocalAI.dmg is ready" build-launcher-linux: - cd cmd/launcher && go run fyne.io/tools/cmd/fyne@latest package -os linux -icon ../../core/http/static/logo.png --executable $(LAUNCHER_BINARY_NAME)-linux && mv launcher.tar.xz ../../$(LAUNCHER_BINARY_NAME)-linux.tar.xz + cd cmd/launcher && go run fyne.io/tools/cmd/fyne@latest package -os linux -icon ../../core/http/static/logo.png --executable $(LAUNCHER_BINARY_NAME)-linux && mv LocalAI.tar.xz ../../$(LAUNCHER_BINARY_NAME)-linux.tar.xz diff --git a/cmd/launcher/FyneApp.toml b/cmd/launcher/FyneApp.toml new file mode 100644 index 000000000..cb0fc38b9 --- /dev/null +++ b/cmd/launcher/FyneApp.toml @@ -0,0 +1,8 @@ +Website = "https://localai.io" + +[Details] +Icon = "../../core/http/static/logo.png" +Name = "LocalAI" +ID = "com.localai.launcher" +Version = "0.0.0" +Build = 1 diff --git a/contrib/macos/Launcher.entitlements b/contrib/macos/Launcher.entitlements new file mode 100644 index 000000000..a46f95113 --- /dev/null +++ b/contrib/macos/Launcher.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + + diff --git a/contrib/macos/sign-and-notarize.sh b/contrib/macos/sign-and-notarize.sh new file mode 100755 index 000000000..73497c769 --- /dev/null +++ b/contrib/macos/sign-and-notarize.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +# Code-sign and notarize macOS artifacts for LocalAI. +# Every sub-command is a no-op (exit 0) when its required secret is unset, +# so unsigned builds (forks, local dev, PRs) keep working. +set -euo pipefail + +ENTITLEMENTS="contrib/macos/Launcher.entitlements" +KEYCHAIN="localai-ci.keychain-db" + +cmd_import_cert() { + if [ -z "${MACOS_CERTIFICATE:-}" ]; then + echo "[sign] MACOS_CERTIFICATE unset: skipping cert import (unsigned build)" + return 0 + fi + local certfile keychain_pwd default_keychain + certfile="$(mktemp).p12" + keychain_pwd="${MACOS_CI_KEYCHAIN_PWD:?MACOS_CI_KEYCHAIN_PWD required when signing}" + echo "$MACOS_CERTIFICATE" | base64 --decode > "$certfile" + security create-keychain -p "$keychain_pwd" "$KEYCHAIN" + security set-keychain-settings -lut 21600 "$KEYCHAIN" + security unlock-keychain -p "$keychain_pwd" "$KEYCHAIN" + security import "$certfile" -k "$KEYCHAIN" -P "${MACOS_CERTIFICATE_PWD:?}" \ + -T /usr/bin/codesign -T /usr/bin/security + security set-key-partition-list -S apple-tool:,apple:,codesign: \ + -s -k "$keychain_pwd" "$KEYCHAIN" >/dev/null + default_keychain="$(security default-keychain | tr -d ' "')" + security list-keychains -d user -s "$KEYCHAIN" "$default_keychain" + rm -f "$certfile" + echo "[sign] certificate imported into $KEYCHAIN" +} + +cmd_sign() { + local target="$1" + if [ -z "${MACOS_SIGN_IDENTITY:-}" ]; then + echo "[sign] MACOS_SIGN_IDENTITY unset: skipping codesign of $target" + return 0 + fi + case "$target" in + *.app) + # Hardened runtime + entitlements are required for notarizing the app bundle. + codesign --deep --force --options runtime --timestamp \ + --entitlements "$ENTITLEMENTS" \ + --sign "$MACOS_SIGN_IDENTITY" "$target" + ;; + *) + # A disk image carries no entitlements/runtime; just sign the container. + codesign --force --timestamp --sign "$MACOS_SIGN_IDENTITY" "$target" + ;; + esac + codesign --verify --strict --verbose=2 "$target" + echo "[sign] signed $target" +} + +cmd_notarize() { + local dmg="$1" + if [ -z "${MACOS_NOTARY_KEY:-}" ]; then + echo "[notarize] MACOS_NOTARY_KEY unset: skipping notarization of $dmg" + return 0 + fi + local keyfile + keyfile="$(mktemp).p8" + echo "$MACOS_NOTARY_KEY" | base64 --decode > "$keyfile" + xcrun notarytool submit "$dmg" \ + --key "$keyfile" \ + --key-id "${MACOS_NOTARY_KEY_ID:?}" \ + --issuer "${MACOS_NOTARY_ISSUER_ID:?}" \ + --wait + rm -f "$keyfile" + xcrun stapler staple "$dmg" + xcrun stapler validate "$dmg" + echo "[notarize] notarized and stapled $dmg" +} + +main() { + local sub="${1:-}"; shift || true + case "$sub" in + import-cert) cmd_import_cert ;; + sign) cmd_sign "$@" ;; + notarize) cmd_notarize "$@" ;; + *) echo "usage: $0 {import-cert|sign |notarize }" >&2; exit 2 ;; + esac +} + +main "$@" diff --git a/docs/content/installation/macos.md b/docs/content/installation/macos.md index fc254cedb..dfda42df2 100644 --- a/docs/content/installation/macos.md +++ b/docs/content/installation/macos.md @@ -22,13 +22,16 @@ Download the latest DMG from GitHub releases: 3. Drag the LocalAI application to your Applications folder 4. Launch LocalAI from your Applications folder -## Known Issues +## Verification -> **Note**: The DMGs are not signed by Apple and may show as quarantined. -> -> **Workaround**: See [this issue](https://github.com/mudler/LocalAI/issues/6268) for details on how to bypass the quarantine. -> -> **Fix tracking**: The signing issue is being tracked in [this issue](https://github.com/mudler/LocalAI/issues/6244). +The `LocalAI.dmg` (and the app inside it) and the `local-ai` server binary are +signed with an Apple Developer ID and notarized by Apple, so they launch with no +quarantine prompt or workaround. To inspect the signature yourself: + +```bash +spctl --assess --type open --context context:primary-signature -v /Applications/LocalAI.app +codesign --verify --deep --strict --verbose=2 /Applications/LocalAI.app +``` ## Next Steps