From 511e6abc7d268667b9c8068024d347852c030936 Mon Sep 17 00:00:00 2001 From: rader Date: Sun, 19 Jul 2026 15:47:11 +0800 Subject: [PATCH] Fix llama-server version selection --- internal/inference/llama.go | 23 ++++++++++++++++++++++- internal/inference/llama_binary_test.go | 14 ++++++++++++++ scripts/install.sh | 5 +++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/internal/inference/llama.go b/internal/inference/llama.go index 0cf8aab..caac163 100644 --- a/internal/inference/llama.go +++ b/internal/inference/llama.go @@ -111,6 +111,17 @@ func findLlamaBinary() string { } } + // Prefer a llama-server installed next to csghub-lite. Background services + // often receive a smaller or differently ordered PATH than the interactive + // shell that ran the installer; searching PATH first can therefore select a + // stale system-wide llama-server instead of the matching co-located release. + exePath, _ := os.Executable() + if sibling := llamaBinarySiblingPath(exePath, runtime.GOOS); sibling != "" { + if _, err := os.Stat(sibling); err == nil { + return sibling + } + } + // Search common names in PATH names := []string{"llama-server", "llama.cpp-server", "llamacpp-server"} for _, name := range names { @@ -120,7 +131,6 @@ func findLlamaBinary() string { } // Check common install locations home, _ := os.UserHomeDir() - exePath, _ := os.Executable() for _, loc := range llamaBinaryCandidatePaths(home, exePath, runtime.GOOS) { if _, err := os.Stat(loc); err == nil { return loc @@ -129,6 +139,17 @@ func findLlamaBinary() string { return "" } +func llamaBinarySiblingPath(exePath, goos string) string { + if strings.TrimSpace(exePath) == "" { + return "" + } + name := "llama-server" + if goos == "windows" { + name += ".exe" + } + return filepath.Join(filepath.Dir(exePath), name) +} + func llamaBinaryCandidatePaths(home, exePath, goos string) []string { name := "llama-server" if goos == "windows" { diff --git a/internal/inference/llama_binary_test.go b/internal/inference/llama_binary_test.go index b911f72..492fac9 100644 --- a/internal/inference/llama_binary_test.go +++ b/internal/inference/llama_binary_test.go @@ -6,6 +6,20 @@ import ( "testing" ) +func TestLlamaBinarySiblingPath(t *testing.T) { + wantName := "llama-server" + if runtime.GOOS == "windows" { + wantName += ".exe" + } + want := filepath.Join("opt", "csghub-lite", wantName) + if got := llamaBinarySiblingPath(filepath.Join("opt", "csghub-lite", "csghub-lite"), runtime.GOOS); got != want { + t.Fatalf("llamaBinarySiblingPath() = %q, want %q", got, want) + } + if got := llamaBinarySiblingPath("", runtime.GOOS); got != "" { + t.Fatalf("llamaBinarySiblingPath(empty) = %q, want empty", got) + } +} + func TestLlamaBinaryCandidatePathsIncludesInstallerLocations(t *testing.T) { home := filepath.Join("Users", "james") exePath := filepath.Join(home, ".local", "bin", "csghub-lite") diff --git a/scripts/install.sh b/scripts/install.sh index 786b2f1..6c003fc 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -799,12 +799,17 @@ install_llama_server() { # @rpath against those compatibility names, not just the versioned payload files. if [ -w "$_llama_dir" ]; then find "$_tmpdir" \( -type f -o -type l \) \( -name "*.dylib" -o -name "*.so" -o -name "*.so.*" \) | while read -r _lib; do + # mv may follow an existing destination symlink instead of replacing + # it, leaving compatibility links pinned to the previous release. + # Remove only the exact incoming basename before installing it. + rm -f "${_llama_dir}/$(basename "$_lib")" mv "$_lib" "$_llama_dir/" done mv "$_llama_bin" "$_llama_dir/" else info "Requires root privileges to install llama-server." find "$_tmpdir" \( -type f -o -type l \) \( -name "*.dylib" -o -name "*.so" -o -name "*.so.*" \) | while read -r _lib; do + run_privileged rm -f "${_llama_dir}/$(basename "$_lib")" run_privileged mv "$_lib" "$_llama_dir/" done run_privileged mv "$_llama_bin" "$_llama_dir/"