* Speed up Studio startup path * Studio: recheck managed binary executability on preflight cache hit and ignore stale unauthenticated platform fetches Preflight: a matching capability cache fingerprint no longer skips the runnability check when the managed binary's executable bit was cleared (size and mtime unchanged, since chmod bumps ctime not mtime). The cache fast path now confirms the binary is still executable, otherwise it falls back to the CLI help probe so preflight reports Stale and can repair, instead of returning Ready and failing later at backend start. Adds a regression test. Frontend: now that first render is no longer gated on fetchDeviceType, the initial unauthenticated health call can resolve after an authenticated platform fetch. Guard the store so a late unauthenticated or failed non-forced response cannot overwrite an already authoritative device type, tunnel URL, or secure flag. Forced refreshes and the first unauthenticated load are unaffected. * Studio: use access(X_OK) for the preflight cache executability guard A mode bitmask treats any execute bit as launchable, but the executable bits can be set only for another owner or group, or be denied by an ACL, so the current user could still hit PermissionDenied at launch and the cached fast path would wrongly return Ready. access(X_OK) checks real executability for the calling user, so an ownership or permission change correctly falls back to the CLI help probe and the Stale repair path. * Studio: ignore any stale non-forced platform fetch once authoritative Extend the platform store guard so a non-forced health response never overwrites an already authoritative result, not only unauthenticated ones. With a saved token the post-render non-forced request can be authenticated but older than a later forced refresh that already picked up the tunnel URL and secure flag; if that earlier request resolves last it would null those fields. Now any non-forced response is dropped once the store holds a server-reported platform. Forced refreshes and the first authoritative write are unaffected. * Studio: run the managed CLI help probe before trusting the preflight cache Restore running the managed CLI help probe before returning Ready from the desktop capability cache, so a managed install whose venv interpreter or a runtime dependency is broken (while path, size, mtime, and markers are unchanged) is reported Stale for repair rather than proceeding to a backend start that cannot spawn. The capability cache still skips the heavier desktop-capabilities probe on a hit, so a warm cache runs one probe instead of two. Removes the executable-access shortcut, which the help probe now subsumes. --------- Co-authored-by: Daniel Han <danielhanchen@gmail.com>
42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-only
|
|
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
|
|
|
|
"""Default Chat model metadata must not block on remote Hugging Face discovery."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
_BACKEND = Path(__file__).resolve().parent.parent
|
|
if str(_BACKEND) not in sys.path:
|
|
sys.path.insert(0, str(_BACKEND))
|
|
|
|
from core.inference.orchestrator import InferenceOrchestrator # noqa: E402
|
|
|
|
|
|
def test_default_models_returns_static_defaults_before_top_fetch(monkeypatch):
|
|
sleep_seconds = 2.0
|
|
|
|
def _slow_fetch(self: InferenceOrchestrator) -> None:
|
|
time.sleep(sleep_seconds)
|
|
self._top_gguf_cache = ["unsloth/slow-GGUF"]
|
|
self._top_models_ready.set()
|
|
|
|
monkeypatch.setattr(InferenceOrchestrator, "_fetch_top_models", _slow_fetch)
|
|
|
|
orchestrator = InferenceOrchestrator()
|
|
started = time.monotonic()
|
|
defaults = orchestrator.default_models
|
|
elapsed = time.monotonic() - started
|
|
|
|
assert elapsed < 0.5, f"default_models blocked for {elapsed:.2f}s"
|
|
assert defaults == orchestrator._static_models
|
|
assert "unsloth/slow-GGUF" not in defaults
|
|
|
|
deadline = time.monotonic() + sleep_seconds + 5
|
|
while not orchestrator._top_models_ready.is_set() and time.monotonic() < deadline:
|
|
time.sleep(0.05)
|
|
|
|
assert "unsloth/slow-GGUF" in orchestrator.default_models
|