Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
pre-commit-ci[bot]
410299b5a6 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-06-11 17:17:31 +00:00
shimmyshimmer
b0dff621b6 Fix llama.cpp update banner offering a downgrade when /releases/latest lags
The update banner decided update_available with a plain tag inequality
(installed != latest). GitHub's /releases/latest endpoint sorts by the
commit date of the release target, not by build number, so when fork
releases land out of order it can return an older build than the one the
installer just resolved from upstream. Users then saw a persistent banner
like b9596 -> b9594 right after updating, which looks like a downgrade
prompt and never goes away.

Compare bNNNN build numbers on the prebuilt marker path (mirroring what
the source-build path already did) and only offer real upgrades, with tag
inequality kept as the fallback for non-bNNNN tags. Apply the same guard
to the freshness stale flag so the CLI warning cannot report a downgrade
either.

Reported in https://www.reddit.com/r/unsloth/comments/1u34fa3/
2026-06-11 10:16:40 -07:00
4 changed files with 78 additions and 4 deletions

View file

@ -222,6 +222,34 @@ def test_check_prebuilt_freshness_not_stale_when_tag_matches(monkeypatch, tmp_pa
assert info["latest_tag"] == "b9300"
def test_check_prebuilt_freshness_not_stale_when_installed_newer(monkeypatch, tmp_path):
"""/releases/latest can lag behind out-of-order fork releases; an installed
build newer than "latest" must never be flagged stale."""
install_dir = tmp_path / "llama.cpp"
_write_marker(
install_dir,
tag = "b9596",
installed_at_utc = (datetime.now(tz = timezone.utc) - timedelta(days = 30))
.isoformat()
.replace("+00:00", "Z"),
)
bin_path = _fake_binary(install_dir, layout = "root")
monkeypatch.setattr(fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9594")
info = fr.check_prebuilt_freshness(str(bin_path))
assert info["stale"] is False
assert info["installed_tag"] == "b9596"
assert info["latest_tag"] == "b9594"
def test_parse_build_number():
assert fr.parse_build_number("b9596") == 9596
assert fr.parse_build_number(" b9596 ") == 9596
assert fr.parse_build_number("9596") is None
assert fr.parse_build_number("b9596-custom") is None
assert fr.parse_build_number("") is None
assert fr.parse_build_number(None) is None
def test_check_prebuilt_freshness_not_stale_within_threshold(monkeypatch, tmp_path):
# Behind by tag but within the 3-day grace window.
install_dir = tmp_path / "llama.cpp"

View file

@ -275,6 +275,26 @@ def test_status_up_to_date(monkeypatch, tmp_path):
assert st["update_available"] is False
def test_status_installed_newer_than_latest_release_not_offered(monkeypatch, tmp_path):
"""GitHub /releases/latest sorts by commit date and can return an older
build than the one just installed; never offer that as an "update"."""
binary = _write_install(tmp_path, "b9596")
monkeypatch.setattr(upd, "_find_binary", lambda: binary)
monkeypatch.setattr(freshness, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9594")
st = upd.get_update_status(force_refresh = True)
assert st["installed_tag"] == "b9596"
assert st["latest_tag"] == "b9594"
assert st["update_available"] is False
def test_status_non_numeric_tags_fall_back_to_inequality(monkeypatch, tmp_path):
binary = _write_install(tmp_path, "custom-build")
monkeypatch.setattr(upd, "_find_binary", lambda: binary)
monkeypatch.setattr(freshness, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9594")
st = upd.get_update_status(force_refresh = True)
assert st["update_available"] is True
def test_start_update_no_marker_no_prebuilt_refuses(monkeypatch, tmp_path):
binary = tmp_path / "llama-server"
binary.write_text("stub") # no marker

View file

@ -13,6 +13,7 @@ from __future__ import annotations
import json
import os
import re
import time
from datetime import datetime, timezone
from pathlib import Path
@ -43,6 +44,14 @@ def _cache_dir() -> Path:
return Path.home() / ".unsloth" / "studio" / "cache" / "llama_cpp_freshness"
def parse_build_number(tag: object) -> Optional[int]:
"""Numeric build from a ``bNNNN`` tag, None for anything else."""
if not isinstance(tag, str):
return None
m = re.fullmatch(r"b(\d+)", tag.strip())
return int(m.group(1)) if m else None
def read_install_marker(binary_path: Optional[str]) -> Optional[dict]:
"""Walk up from binary_path to find UNSLOTH_PREBUILT_INFO.json.
None = no marker (source build / custom path) or invalid JSON."""
@ -208,6 +217,14 @@ def check_prebuilt_freshness(
if not latest or latest == out["installed_tag"]:
return out
# GitHub /releases/latest sorts by commit date, not build number, so it can
# lag the installed build when releases land out of order; never call a
# downgrade stale.
installed_build = parse_build_number(out["installed_tag"])
latest_build = parse_build_number(latest)
if installed_build is not None and latest_build is not None and latest_build <= installed_build:
return out
installed_at = _parse_installed_at(out["installed_at_utc"])
if installed_at is None:
return out

View file

@ -10,7 +10,8 @@ the next model load uses it.
Design notes:
- Detection is delegated to check_prebuilt_freshness(). We surface an
``update_available`` flag (installed_tag != latest_tag) which is laxer than
``update_available`` flag (installed build older than the latest release;
tag inequality only when either tag is not bNNNN) which is laxer than
freshness' ``stale`` (which additionally requires the install to be >= 3 days
old). The UI shows the "Update llama.cpp" affordance on update_available.
- The install is slow (download + extract + validate), so it runs on a daemon
@ -37,6 +38,7 @@ from utils.llama_cpp_freshness import (
_INSTALL_MARKER_NAME,
check_prebuilt_freshness,
latest_published_release,
parse_build_number,
read_install_marker,
reset_caches,
)
@ -286,9 +288,16 @@ def get_update_status(*, force_refresh: bool = False) -> dict:
freshness = check_prebuilt_freshness(binary)
installed = freshness.get("installed_tag")
latest = freshness.get("latest_tag")
update_available = bool(
freshness.get("has_marker") and installed and latest and installed != latest
)
# GitHub /releases/latest sorts by commit date, so it can point at an older
# build than the one the installer just resolved; compare build numbers and
# only offer real upgrades. Tag inequality is the fallback for non-bNNNN tags.
installed_build = parse_build_number(installed)
latest_build = parse_build_number(latest)
if installed_build is not None and latest_build is not None:
behind = installed_build < latest_build
else:
behind = installed != latest
update_available = bool(freshness.get("has_marker") and installed and latest and behind)
with _job_lock:
job = dict(_job)