personal memory agent
0

Configure Feed

Select the types of activity you want to include in your feed.

solstone / tests / test_local_install.py
74 kB 2134 lines
1# SPDX-License-Identifier: AGPL-3.0-only 2# Copyright (c) 2026 sol pbc 3 4from __future__ import annotations 5 6import json 7import shutil 8import subprocess 9import tarfile 10import time 11from dataclasses import replace 12from pathlib import Path 13from types import SimpleNamespace 14from urllib.parse import urlparse 15 16import pytest 17 18from solstone.think.models import LOCAL_MODEL 19from solstone.think.providers import ( 20 fit_report, 21 local_cuda, 22 local_install, 23 local_vulkan, 24 memory, 25) 26from solstone.think.providers.artifact_proof import ( 27 ProofResult, 28 ReadinessOutcome, 29 artifact_manifest_path, 30 prove_manifest, 31) 32from solstone.think.providers.install_state import ( 33 begin_or_replace_install_attempt, 34 canonical_fingerprint, 35 fingerprint_sha256, 36 read_install_status, 37 transition_state, 38 write_install_status, 39) 40from solstone.think.providers.local import LOCAL_MODEL_SPECS 41from solstone.think.providers.local_endpoint import resolve_local_endpoint 42 43 44def _init_journal(tmp_path, monkeypatch) -> None: 45 config_dir = tmp_path / "config" 46 config_dir.mkdir(parents=True) 47 (config_dir / "journal.json").write_text( 48 json.dumps({"providers": {}}) + "\n", 49 encoding="utf-8", 50 ) 51 monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path)) 52 53 54def _local_status() -> dict: 55 return read_install_status(name="local") 56 57 58def _write_provider_local_config(tmp_path: Path, updates: dict[str, object]) -> None: 59 path = tmp_path / "config" / "journal.json" 60 config = json.loads(path.read_text(encoding="utf-8")) 61 provider_config = config.setdefault("providers", {}).setdefault("local", {}) 62 provider_config.update(updates) 63 path.write_text(json.dumps(config) + "\n", encoding="utf-8") 64 65 66def _fake_local_readiness( 67 *, 68 binary_installed: bool, 69 model_installed: bool, 70 binary_path: Path, 71 model_path: Path, 72 mmproj_path: Path | None = None, 73 ram_sufficient: bool = True, 74 backend: str = "vulkan", 75 backend_reason: str = "test vulkan", 76) -> ReadinessOutcome: 77 missing_binary = not binary_installed 78 missing_model = not model_installed 79 status = ( 80 "ready" if not missing_binary and not missing_model else "missing-or-mismatched" 81 ) 82 reason_code = ( 83 "ready" 84 if status == "ready" 85 else "binary_missing" 86 if missing_binary 87 else "model_missing" 88 ) 89 binary_status = "ready" if binary_installed else "missing-or-mismatched" 90 model_status = "ready" if model_installed else "missing-or-mismatched" 91 return ReadinessOutcome( 92 provider=local_install.LOCAL_PROVIDER_NAME, 93 status=status, 94 reason_code=reason_code, 95 target={"model_id": LOCAL_MODEL}, 96 install={ 97 "install_state": "idle", 98 "install_error": None, 99 "error_code": None, 100 "attempt_id": None, 101 "progress_bytes_received": None, 102 "progress_bytes_total": None, 103 "last_transition_at": None, 104 "last_progress_at": None, 105 }, 106 host={ 107 "ram_sufficient": ram_sufficient, 108 "gpu_available": True, 109 "gpu_probe_ok": True, 110 "backend": backend, 111 "backend_reason": backend_reason, 112 }, 113 artifacts={ 114 "binary_installed": binary_installed, 115 "model_installed": model_installed, 116 "binary_path": str(binary_path), 117 "model_path": str(model_path), 118 "mmproj_path": str(mmproj_path) if mmproj_path is not None else None, 119 }, 120 proof={ 121 "binary": { 122 "status": binary_status, 123 "reason_code": "ready" if binary_installed else "manifest_missing", 124 "cache_hit": False, 125 }, 126 "model": { 127 "status": model_status, 128 "reason_code": "ready" if model_installed else "manifest_missing", 129 "cache_hit": False, 130 }, 131 }, 132 ) 133 134 135def _write_ready_vulkan_manifest( 136 *, 137 artifact_key: str | None = None, 138 pin: dict[str, str] | None = None, 139) -> None: 140 resolved_pin = pin or local_install.pin_for_current_platform() 141 resolved_key = artifact_key or local_install.llama_server_artifact_key() 142 local_install._write_vulkan_manifest( 143 artifact_key=resolved_key, 144 pin=resolved_pin, 145 attempt_status=None, 146 fingerprint=local_install.target_fingerprint(LOCAL_MODEL), 147 ) 148 149 150def _write_ready_model_manifest(model_id: str = LOCAL_MODEL) -> None: 151 local_install._write_model_manifest( 152 model_id=model_id, 153 attempt_status=None, 154 fingerprint=local_install.target_fingerprint(model_id), 155 ) 156 157 158def _fit(severity: fit_report.FitSeverity) -> fit_report.FitReport: 159 return fit_report.FitReport( 160 artifact="test local", 161 checks=(fit_report.FitCheck("test", severity, f"{severity} detail"),), 162 ) 163 164 165def _covered_nvidia_probe( 166 *, 167 compute_cap: str = "sm_121", 168 driver_cuda_version: int = 13, 169 vram_mib: int = 24564, 170) -> local_cuda.NvidiaProbe: 171 return local_cuda.NvidiaProbe( 172 index=0, 173 compute_cap=compute_cap, 174 driver_cuda_version=driver_cuda_version, 175 vram_mib=vram_mib, 176 tiering_memory_mib=vram_mib, 177 memory_source=local_cuda.MEMORY_SOURCE_NVIDIA_VRAM, 178 detected=True, 179 ) 180 181 182def _patch_backend_inputs( 183 monkeypatch: pytest.MonkeyPatch, 184 *, 185 compute_cap: str, 186 driver_cuda_version: int, 187 trust: local_cuda.ArtifactTrust, 188 persisted_installed_cuda: bool = False, 189) -> None: 190 monkeypatch.setattr( 191 local_cuda, 192 "probe_nvidia_gpu", 193 lambda: _covered_nvidia_probe( 194 compute_cap=compute_cap, 195 driver_cuda_version=driver_cuda_version, 196 ), 197 ) 198 monkeypatch.setattr( 199 local_install, 200 "probe_cuda_runtime_artifact_trust", 201 lambda _pin, **_kwargs: trust, 202 ) 203 monkeypatch.setattr( 204 local_install, 205 "has_persisted_installed_cuda_target", 206 lambda **_kwargs: persisted_installed_cuda, 207 ) 208 209 210def _force_cuda_backend(monkeypatch: pytest.MonkeyPatch) -> None: 211 _patch_backend_inputs( 212 monkeypatch, 213 compute_cap="sm_121", 214 driver_cuda_version=13, 215 trust=local_cuda.ArtifactTrust.TRUSTED, 216 ) 217 218 219@pytest.mark.parametrize( 220 ("status", "expected"), 221 [ 222 ("ready", local_cuda.ArtifactTrust.TRUSTED), 223 ("missing-or-mismatched", local_cuda.ArtifactTrust.ABSENT), 224 ("proof-unavailable", local_cuda.ArtifactTrust.UNAVAILABLE), 225 ], 226) 227@pytest.mark.real_local_backend_probe 228def test_probe_cuda_runtime_artifact_trust_maps_proof_status( 229 monkeypatch: pytest.MonkeyPatch, 230 status: str, 231 expected: local_cuda.ArtifactTrust, 232) -> None: 233 monkeypatch.setattr( 234 local_install, 235 "cuda_artifact_pin_for_current_platform", 236 lambda _pin=None: None, 237 ) 238 monkeypatch.setattr( 239 local_install, 240 "_prove_cuda_runtime_artifact", 241 lambda _pin, **_kwargs: ProofResult(status, "test"), 242 ) 243 244 assert ( 245 local_install.probe_cuda_runtime_artifact_trust(local_install.CUDA_SERVER_PIN) 246 == expected 247 ) 248 249 250@pytest.mark.real_local_backend_probe 251def test_probe_cuda_runtime_artifact_trust_uses_present_pin_without_local_manifest( 252 monkeypatch: pytest.MonkeyPatch, 253) -> None: 254 def fail_proof(_pin, **_kwargs): 255 raise AssertionError("present platform pin should short-circuit proof") 256 257 monkeypatch.setattr(local_install, "_prove_cuda_runtime_artifact", fail_proof) 258 259 assert ( 260 local_install.probe_cuda_runtime_artifact_trust(local_install.CUDA_SERVER_PIN) 261 == local_cuda.ArtifactTrust.TRUSTED 262 ) 263 264 265@pytest.mark.real_local_backend_probe 266def test_probe_cuda_runtime_artifact_trust_contains_unexpected_exception( 267 monkeypatch: pytest.MonkeyPatch, 268 caplog: pytest.LogCaptureFixture, 269) -> None: 270 def fail_proof(_pin, **_kwargs): 271 raise ValueError("required artifact is not a regular file") 272 273 monkeypatch.setattr( 274 local_install, 275 "cuda_artifact_pin_for_current_platform", 276 lambda _pin=None: None, 277 ) 278 monkeypatch.setattr(local_install, "_prove_cuda_runtime_artifact", fail_proof) 279 280 trust = local_install.probe_cuda_runtime_artifact_trust( 281 local_install.CUDA_SERVER_PIN 282 ) 283 284 assert trust == local_cuda.ArtifactTrust.UNAVAILABLE 285 assert "trust probe failed" in caplog.text 286 287 288@pytest.mark.real_local_backend_probe 289def test_probe_cuda_runtime_artifact_trust_absent_without_platform_pin( 290 tmp_path: Path, 291 monkeypatch: pytest.MonkeyPatch, 292) -> None: 293 _init_journal(tmp_path, monkeypatch) 294 monkeypatch.setattr(local_install.platform, "machine", lambda: "x86_64") 295 pin = replace(local_install.CUDA_SERVER_PIN, artifacts_by_key={}) 296 297 assert ( 298 local_install.probe_cuda_runtime_artifact_trust(pin, journal_path=tmp_path) 299 == local_cuda.ArtifactTrust.ABSENT 300 ) 301 302 303@pytest.mark.real_local_backend_probe 304def test_has_persisted_installed_cuda_target_reads_installed_backend( 305 tmp_path: Path, 306 monkeypatch: pytest.MonkeyPatch, 307) -> None: 308 _init_journal(tmp_path, monkeypatch) 309 cuda_target = { 310 "provider": "local", 311 "runtime": "llama.cpp", 312 "backend": "cuda", 313 "model_pin": {"model_id": LOCAL_MODEL}, 314 } 315 vulkan_target = {**cuda_target, "backend": "vulkan"} 316 317 status = begin_or_replace_install_attempt("local", cuda_target) 318 write_install_status(transition_state(status, new_state="installed")) 319 assert ( 320 local_install.has_persisted_installed_cuda_target(journal_path=tmp_path) is True 321 ) 322 323 status = begin_or_replace_install_attempt("local", vulkan_target) 324 write_install_status(transition_state(status, new_state="installed")) 325 assert ( 326 local_install.has_persisted_installed_cuda_target(journal_path=tmp_path) 327 is False 328 ) 329 330 331@pytest.mark.real_local_backend_probe 332def test_has_persisted_installed_cuda_target_treats_bad_status_as_false( 333 tmp_path: Path, 334 monkeypatch: pytest.MonkeyPatch, 335) -> None: 336 _init_journal(tmp_path, monkeypatch) 337 path = tmp_path / "health" / "providers" / "local.json" 338 path.parent.mkdir(parents=True) 339 path.write_text("{not-json", encoding="utf-8") 340 341 assert ( 342 local_install.has_persisted_installed_cuda_target(journal_path=tmp_path) 343 is False 344 ) 345 346 347def test_target_fingerprint_uses_cuda_when_platform_pin_present_on_covered_host( 348 tmp_path: Path, 349 monkeypatch: pytest.MonkeyPatch, 350) -> None: 351 _init_journal(tmp_path, monkeypatch) 352 _patch_backend_inputs( 353 monkeypatch, 354 compute_cap="sm_86", 355 driver_cuda_version=14, 356 trust=local_cuda.ArtifactTrust.TRUSTED, 357 ) 358 359 fingerprint = local_install.target_fingerprint(LOCAL_MODEL) 360 361 assert fingerprint["backend"] == "cuda" 362 assert ( 363 fingerprint["backend_reason"] 364 == "compute_cap sm_86 covered; driver CUDA 14 >= 13" 365 ) 366 367 368def test_target_fingerprint_holds_cuda_when_trust_unavailable_and_cuda_installed( 369 tmp_path: Path, 370 monkeypatch: pytest.MonkeyPatch, 371) -> None: 372 _init_journal(tmp_path, monkeypatch) 373 _patch_backend_inputs( 374 monkeypatch, 375 compute_cap="sm_89", 376 driver_cuda_version=15, 377 trust=local_cuda.ArtifactTrust.UNAVAILABLE, 378 persisted_installed_cuda=True, 379 ) 380 381 fingerprint = local_install.target_fingerprint(LOCAL_MODEL) 382 383 assert fingerprint["backend"] == "cuda" 384 assert fingerprint["backend_reason"] == ( 385 "compute_cap sm_89 covered; driver CUDA 15 >= 13" 386 ) 387 388 389def test_target_fingerprint_uses_cuda_when_runtime_pin_is_trusted( 390 tmp_path: Path, 391 monkeypatch: pytest.MonkeyPatch, 392) -> None: 393 _init_journal(tmp_path, monkeypatch) 394 _patch_backend_inputs( 395 monkeypatch, 396 compute_cap="sm_121", 397 driver_cuda_version=16, 398 trust=local_cuda.ArtifactTrust.TRUSTED, 399 persisted_installed_cuda=False, 400 ) 401 402 fingerprint = local_install.target_fingerprint(LOCAL_MODEL) 403 404 assert fingerprint["backend"] == "cuda" 405 assert fingerprint["backend_reason"] == ( 406 "compute_cap sm_121 covered; driver CUDA 16 >= 13" 407 ) 408 409 410def _write_probe_script(tmp_path: Path, body: str) -> Path: 411 script = tmp_path / "probe.sh" 412 script.write_text(f"#!/bin/sh\n{body}\n", encoding="utf-8") 413 script.chmod(0o755) 414 return script 415 416 417class _FakeStream: 418 def __init__( 419 self, 420 chunks: list[bytes], 421 chunk_times: list[float], 422 total: int | None, 423 clock: list[float], 424 ) -> None: 425 self._chunks = chunks 426 self._chunk_times = chunk_times 427 self.headers = {"content-length": str(total)} if total is not None else {} 428 self._clock = clock 429 430 def __enter__(self): 431 return self 432 433 def __exit__(self, *_exc): 434 return False 435 436 def raise_for_status(self): 437 return None 438 439 def iter_bytes(self): 440 for chunk, t in zip(self._chunks, self._chunk_times, strict=True): 441 self._clock[0] = t 442 yield chunk 443 444 445def _download_with_fake_stream( 446 tmp_path: Path, 447 monkeypatch: pytest.MonkeyPatch, 448 chunks: list[bytes], 449 chunk_times: list[float], 450) -> tuple[Path, list[tuple[int, int | None]]]: 451 total = sum(len(chunk) for chunk in chunks) 452 calls: list[tuple[int, int | None]] = [] 453 454 def fake_stream(method, url, **_kwargs): 455 assert method == "GET" 456 assert url == "https://example.test/artifact" 457 return _FakeStream(chunks, chunk_times, total, [0.0]) 458 459 def record_progress(received: int, reported_total: int | None) -> None: 460 calls.append((received, reported_total)) 461 462 monkeypatch.setattr("httpx.stream", fake_stream) 463 dest = tmp_path / "artifact.bin" 464 local_install._download_file( 465 "https://example.test/artifact", 466 dest, 467 on_progress=record_progress, 468 ) 469 return dest, calls 470 471 472def test_install_hint_literal() -> None: 473 assert local_install.install_hint() == "journal install-provider local" 474 475 476def test_download_file_reports_each_progress_chunk(tmp_path, monkeypatch): 477 chunks = [b"x"] * 20 478 chunk_times = [index * 0.01 for index in range(len(chunks))] 479 480 _dest, calls = _download_with_fake_stream( 481 tmp_path, monkeypatch, chunks, chunk_times 482 ) 483 484 total = sum(len(chunk) for chunk in chunks) 485 assert calls == [(index, total) for index in range(1, len(chunks) + 1)] 486 487 488def test_download_file_emits_first_progress_promptly(tmp_path, monkeypatch): 489 chunks = [b"abc", b"de"] 490 chunk_times = [0.4, 0.5] 491 492 _dest, calls = _download_with_fake_stream( 493 tmp_path, monkeypatch, chunks, chunk_times 494 ) 495 496 assert calls[0] == (len(chunks[0]), sum(len(chunk) for chunk in chunks)) 497 498 499def test_download_file_emits_interval_crossing_progress(tmp_path, monkeypatch): 500 chunks = [b"a", b"bb", b"ccc", b"dddd", b"eeeee"] 501 chunk_times = [0.0, 0.1, 0.2, 1.5, 1.6] 502 503 _dest, calls = _download_with_fake_stream( 504 tmp_path, monkeypatch, chunks, chunk_times 505 ) 506 507 total = sum(len(chunk) for chunk in chunks) 508 expected = [] 509 received = 0 510 for chunk in chunks: 511 received += len(chunk) 512 expected.append((received, total)) 513 assert calls == expected 514 515 516def test_download_file_emits_each_final_chunk_once(tmp_path, monkeypatch): 517 chunks = [b"aa", b"bbb"] 518 519 _dest, inside_window_calls = _download_with_fake_stream( 520 tmp_path, 521 monkeypatch, 522 chunks, 523 [0.0, 0.2], 524 ) 525 total = sum(len(chunk) for chunk in chunks) 526 assert inside_window_calls[-1] == (total, total) 527 assert inside_window_calls.count((total, total)) == 1 528 529 _dest, last_chunk_emit_calls = _download_with_fake_stream( 530 tmp_path, 531 monkeypatch, 532 chunks, 533 [0.0, 1.5], 534 ) 535 assert len(last_chunk_emit_calls) == 2 536 assert last_chunk_emit_calls.count((total, total)) == 1 537 538 539def test_download_file_writes_dest_and_replaces_tmp(tmp_path, monkeypatch): 540 chunks = [b"ab", b"cd", b"ef"] 541 chunk_times = [0.0, 0.1, 0.2] 542 543 dest, _calls = _download_with_fake_stream( 544 tmp_path, monkeypatch, chunks, chunk_times 545 ) 546 547 assert dest.read_bytes() == b"".join(chunks) 548 assert not dest.with_suffix(dest.suffix + ".tmp").exists() 549 550 551@pytest.mark.parametrize( 552 ("machine", "arch"), 553 [ 554 ("x86_64", "amd64"), 555 ("amd64", "amd64"), 556 ("x64", "amd64"), 557 ("aarch64", "arm64"), 558 ("arm64", "arm64"), 559 ], 560) 561def test_cuda_runtime_arch_mapping( 562 machine: str, arch: str, monkeypatch: pytest.MonkeyPatch 563): 564 monkeypatch.setattr(local_install.platform, "machine", lambda: machine) 565 566 assert local_install._cuda_runtime_arch() == arch 567 568 569def test_cuda_runtime_arch_unsupported_raises(monkeypatch: pytest.MonkeyPatch): 570 monkeypatch.setattr(local_install.platform, "machine", lambda: "riscv64") 571 572 with pytest.raises(local_install.LocalProviderError) as exc_info: 573 local_install._cuda_runtime_arch() 574 575 assert exc_info.value.reason_code == "unsupported_platform" 576 577 578def test_cuda_binary_paths_include_tarball_sha256(tmp_path, monkeypatch): 579 _init_journal(tmp_path, monkeypatch) 580 artifact_pin = local_install.require_cuda_artifact_pin_for_current_platform() 581 582 assert local_install.cuda_binary_dir() == ( 583 tmp_path 584 / "cache" 585 / "providers" 586 / "local" 587 / "cuda" 588 / local_install.llama_server_artifact_key() 589 / artifact_pin.sha256 590 ) 591 assert local_install.cuda_binary_path() == ( 592 local_install.cuda_binary_dir() / local_install.CUDA_SERVER_PIN.binary_name 593 ) 594 595 596@pytest.mark.parametrize( 597 ("arch", "expected_cpu", "unexpected_cpu", "cpu_count"), 598 [ 599 ("amd64", "libggml-cpu-haswell.so", "libggml-cpu-armv8.0_1.so", 14), 600 ("arm64", "libggml-cpu-armv8.0_1.so", "libggml-cpu-haswell.so", 8), 601 ], 602) 603def test_cuda_server_pin_wanted_files_are_arch_specific( 604 arch: str, 605 expected_cpu: str, 606 unexpected_cpu: str, 607 cpu_count: int, 608) -> None: 609 wanted_files = local_install.CUDA_SERVER_PIN.wanted_files_for_arch(arch) 610 cpu_files = [name for name in wanted_files if name.startswith("libggml-cpu-")] 611 612 assert "llama-server" in wanted_files 613 assert "libcudart.so.13" in wanted_files 614 assert "libcublas.so.13" in wanted_files 615 assert expected_cpu in wanted_files 616 assert unexpected_cpu not in wanted_files 617 assert len(cpu_files) == cpu_count 618 619 620def test_cuda_server_pin_wanted_files_reject_unknown_arch() -> None: 621 with pytest.raises(local_install.LocalProviderError) as exc_info: 622 local_install.CUDA_SERVER_PIN.wanted_files_for_arch("ppc64le") 623 624 assert exc_info.value.reason_code == "unsupported_platform" 625 626 627def test_llama_server_pins_are_complete_immutable_artifacts() -> None: 628 expected = { 629 "aarch64-apple-darwin": { 630 "release_tag": "b10068", 631 "filename": "llama-b10068-bin-macos-arm64.tar.gz", 632 "sha256": "13aa2d40c76ad1dcb8ebeec5f0d2814bf3b2f84a66935c7d4dc6f7cca8e38d68", 633 "binary_name": "llama-server", 634 }, 635 "x86_64-unknown-linux-gnu": { 636 "release_tag": "b10068", 637 "filename": "llama-b10068-bin-ubuntu-vulkan-x64.tar.gz", 638 "sha256": "713641920dce6c8efb953ebc9ffa309977e200cec5e182e6ad0e8b086203cdc3", 639 "binary_name": "llama-server", 640 }, 641 "aarch64-unknown-linux-gnu": { 642 "release_tag": "b10068", 643 "filename": "llama-b10068-bin-ubuntu-vulkan-arm64.tar.gz", 644 "sha256": "c3c49e6e124a574165ca28317be021b1a12a2ea06977e3eb7daee3eb443eb186", 645 "binary_name": "llama-server", 646 }, 647 } 648 pins = local_install.LLAMA_SERVER_PINS 649 650 assert set(pins) == set(expected) 651 for key, expected_pin in expected.items(): 652 assert pins[key] == expected_pin 653 654 655def test_cuda_server_artifact_pins_are_complete_immutable_artifacts() -> None: 656 expected = { 657 "x86_64-unknown-linux-gnu": local_install.CudaArtifactPin( 658 url=( 659 "https://updates.solstone.app/runtimes/llama-cuda13/b10068/" 660 "llama-b10068-bin-linux-cuda13-amd64-sol1.tar.gz" 661 ), 662 sha256="3727630e6ac79953f5c652fddcfd7100da98c55d773c0aec115a55f40f3aafea", 663 size_bytes=550238443, 664 release_tag="b10068", 665 upstream_image_digest=( 666 "sha256:" 667 "5bd5290bd35cfde893d0dcbd9811723c16d89575927d537b5f21becbfbab2f63" 668 ), 669 llama_cpp_revision="571d0d540df04f25298d0e159e520d9fc62ed121", 670 repack_revision="sol1", 671 ), 672 "aarch64-unknown-linux-gnu": local_install.CudaArtifactPin( 673 url=( 674 "https://updates.solstone.app/runtimes/llama-cuda13/b10068/" 675 "llama-b10068-bin-linux-cuda13-arm64-sol1.tar.gz" 676 ), 677 sha256="6de68319db40e8c0eb45dc4bd3a45a16971dbdc128f2b621b19bef5dae87d064", 678 size_bytes=654508507, 679 release_tag="b10068", 680 upstream_image_digest=( 681 "sha256:" 682 "5bd5290bd35cfde893d0dcbd9811723c16d89575927d537b5f21becbfbab2f63" 683 ), 684 llama_cpp_revision="571d0d540df04f25298d0e159e520d9fc62ed121", 685 repack_revision="sol1", 686 ), 687 } 688 689 assert local_install.CUDA_SERVER_PIN.artifacts_by_key == expected 690 for key, artifact_pin in local_install.CUDA_SERVER_PIN.artifacts_by_key.items(): 691 assert artifact_pin.url.startswith("https://updates.solstone.app/runtimes/") 692 assert len(artifact_pin.sha256) == 64 693 assert set(artifact_pin.sha256) <= set("0123456789abcdef") 694 assert artifact_pin.size_bytes > 0 695 assert ( 696 artifact_pin.release_tag 697 == local_install.LLAMA_SERVER_PINS[key]["release_tag"] 698 ) 699 700 701def _write_cuda_runtime_tarball( 702 tmp_path: Path, 703 *, 704 arch: str = "amd64", 705 missing: tuple[str, ...] = (), 706 traversal: bool = False, 707) -> Path: 708 source = tmp_path / "cuda-source" 709 source.mkdir() 710 missing_set = set(missing) 711 for name in local_install.CUDA_SERVER_PIN.wanted_files_for_arch(arch): 712 if name in missing_set: 713 continue 714 path = source / name 715 path.write_text(name, encoding="utf-8") 716 if "licenses/" not in missing_set: 717 licenses = source / "licenses" 718 licenses.mkdir() 719 (licenses / "LICENSE").write_text("license", encoding="utf-8") 720 if "provenance.json" not in missing_set: 721 (source / "provenance.json").write_text("{}\n", encoding="utf-8") 722 723 tarball = tmp_path / "cuda-runtime.tar.gz" 724 with tarfile.open(tarball, "w:gz") as archive: 725 for path in sorted(source.rglob("*")): 726 archive.add(path, arcname=path.relative_to(source).as_posix()) 727 if traversal: 728 escape = tmp_path / "escape-source" 729 escape.write_text("bad", encoding="utf-8") 730 archive.add(escape, arcname="../escape") 731 return tarball 732 733 734def _patch_tarball_download( 735 monkeypatch: pytest.MonkeyPatch, 736 tarball: Path, 737) -> None: 738 def fake_download(_url: str, dest: Path, **kwargs: object) -> None: 739 shutil.copyfile(tarball, dest) 740 on_progress = kwargs.get("on_progress") 741 if on_progress is not None: 742 on_progress(tarball.stat().st_size, tarball.stat().st_size) 743 744 monkeypatch.setattr(local_install, "_download_file", fake_download) 745 746 747def test_install_llama_server_relocates_binary_and_libraries(tmp_path, monkeypatch): 748 _init_journal(tmp_path, monkeypatch) 749 pin = local_install.pin_for_current_platform() 750 if local_install.llama_server_artifact_key() == "x86_64-unknown-linux-gnu": 751 assert pin["filename"] == "llama-b10068-bin-ubuntu-vulkan-x64.tar.gz" 752 assert ( 753 pin["sha256"] 754 == "713641920dce6c8efb953ebc9ffa309977e200cec5e182e6ad0e8b086203cdc3" 755 ) 756 artifact_key = local_install.llama_server_artifact_key() 757 install_dir = local_install.binary_install_dir(artifact_key, pin) 758 binary_path = local_install.binary_path_for_pin(artifact_key, pin) 759 inner_name = "llama-b10068" 760 lib_names = ["libllama.so", "libggml.so", "libfoo.dylib"] 761 fixture_root = tmp_path / "fixture" / inner_name 762 fixture_root.mkdir(parents=True) 763 (fixture_root / pin["binary_name"]).write_bytes(b"fake llama-server") 764 for lib_name in lib_names: 765 (fixture_root / lib_name).write_bytes(f"fake {lib_name}".encode()) 766 fixture_tarball = tmp_path / pin["filename"] 767 with tarfile.open(fixture_tarball, "w:gz") as archive: 768 archive.add(fixture_root, arcname=inner_name) 769 quarantine_calls: list[Path] = [] 770 771 def fake_download(_url, dest, **_kwargs): 772 dest.parent.mkdir(parents=True, exist_ok=True) 773 shutil.copy2(fixture_tarball, dest) 774 775 def record_quarantine(path): 776 quarantine_calls.append(Path(path)) 777 778 monkeypatch.setattr(local_install, "_download_file", fake_download) 779 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 780 monkeypatch.setattr(local_install, "_clear_macos_quarantine", record_quarantine) 781 782 def assert_flat_layout() -> None: 783 assert binary_path.exists() 784 assert binary_path.read_bytes() == b"fake llama-server" 785 for lib_name in lib_names: 786 lib_path = install_dir / lib_name 787 assert lib_path.exists() 788 assert lib_path.read_bytes() == f"fake {lib_name}".encode() 789 assert not (install_dir / inner_name).exists() 790 assert not (install_dir / pin["filename"]).exists() 791 792 result = local_install.install_llama_server() 793 794 assert result["install_state"] == "verifying" 795 assert prove_manifest( 796 artifact_manifest_path(install_dir), 797 provider="local", 798 pin_identity=local_install._vulkan_pin_identity(artifact_key, pin), 799 ).ready 800 assert_flat_layout() 801 assert len(quarantine_calls) == 1 802 assert quarantine_calls[0].parent == install_dir.parent 803 804 result = local_install.install_llama_server() 805 806 assert result["install_state"] == "verifying" 807 assert_flat_layout() 808 assert len(quarantine_calls) == 2 809 assert all(path.parent == install_dir.parent for path in quarantine_calls) 810 811 812def test_install_llama_server_sha256_mismatch_fails_closed_before_extract( 813 tmp_path, monkeypatch 814): 815 _init_journal(tmp_path, monkeypatch) 816 expected_urls = { 817 "aarch64-apple-darwin": ( 818 "https://github.com/ggml-org/llama.cpp/releases/download/b10068/" 819 "llama-b10068-bin-macos-arm64.tar.gz" 820 ), 821 "x86_64-unknown-linux-gnu": ( 822 "https://github.com/ggml-org/llama.cpp/releases/download/b10068/" 823 "llama-b10068-bin-ubuntu-vulkan-x64.tar.gz" 824 ), 825 "aarch64-unknown-linux-gnu": ( 826 "https://github.com/ggml-org/llama.cpp/releases/download/b10068/" 827 "llama-b10068-bin-ubuntu-vulkan-arm64.tar.gz" 828 ), 829 } 830 artifact_key = local_install.llama_server_artifact_key() 831 pin = local_install.pin_for_current_platform() 832 install_dir = local_install.binary_install_dir(artifact_key, pin) 833 binary_path = local_install.binary_path_for_pin(artifact_key, pin) 834 inner_name = "llama-b10068" 835 fixture_root = tmp_path / "fixture" / inner_name 836 fixture_root.mkdir(parents=True) 837 (fixture_root / pin["binary_name"]).write_bytes(b"not the pinned server") 838 fixture_tarball = tmp_path / pin["filename"] 839 with tarfile.open(fixture_tarball, "w:gz") as archive: 840 archive.add(fixture_root, arcname=inner_name) 841 download_urls: list[str] = [] 842 843 def fake_download(url, dest, **_kwargs): 844 download_urls.append(url) 845 dest.parent.mkdir(parents=True, exist_ok=True) 846 shutil.copy2(fixture_tarball, dest) 847 848 monkeypatch.setattr(local_install, "_download_file", fake_download) 849 850 with pytest.raises(local_install.LocalProviderError) as exc_info: 851 local_install.install_llama_server() 852 853 assert exc_info.value.reason_code == "sha256_mismatch" 854 assert download_urls == [expected_urls[artifact_key]] 855 status = _local_status() 856 assert status["install_state"] == "failed" 857 assert status["install_error"] is not None 858 assert status["error_code"] == "sha256_mismatch" 859 assert "sha256 mismatch" in status["install_error"] 860 assert not artifact_manifest_path(install_dir).exists() 861 assert not binary_path.exists() 862 assert not (install_dir / inner_name).exists() 863 assert not install_dir.exists() 864 865 866def test_install_llama_server_extract_failure_preserves_prior_tree( 867 tmp_path, monkeypatch 868): 869 _init_journal(tmp_path, monkeypatch) 870 artifact_key = local_install.llama_server_artifact_key() 871 pin = local_install.pin_for_current_platform() 872 install_dir = local_install.binary_install_dir(artifact_key, pin) 873 binary = local_install.binary_path_for_pin(artifact_key, pin) 874 binary.parent.mkdir(parents=True, exist_ok=True) 875 binary.write_bytes(b"old binary") 876 binary.chmod(0o755) 877 _write_ready_vulkan_manifest(artifact_key=artifact_key, pin=pin) 878 old_manifest = artifact_manifest_path(install_dir).read_text(encoding="utf-8") 879 880 def fake_download(_url, dest, **_kwargs): 881 dest.parent.mkdir(parents=True, exist_ok=True) 882 dest.write_bytes(b"archive") 883 884 monkeypatch.setattr(local_install, "_download_file", fake_download) 885 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 886 monkeypatch.setattr( 887 local_install, 888 "_safe_extract_tarball", 889 lambda _tarball, _dest: (_ for _ in ()).throw(RuntimeError("extract broke")), 890 ) 891 892 with pytest.raises(RuntimeError, match="extract broke"): 893 local_install.install_llama_server() 894 895 assert binary.read_bytes() == b"old binary" 896 assert ( 897 artifact_manifest_path(install_dir).read_text(encoding="utf-8") == old_manifest 898 ) 899 900 901def test_install_llama_server_manifest_failure_preserves_prior_tree( 902 tmp_path, monkeypatch 903): 904 _init_journal(tmp_path, monkeypatch) 905 artifact_key = local_install.llama_server_artifact_key() 906 pin = local_install.pin_for_current_platform() 907 install_dir = local_install.binary_install_dir(artifact_key, pin) 908 binary = local_install.binary_path_for_pin(artifact_key, pin) 909 binary.parent.mkdir(parents=True, exist_ok=True) 910 binary.write_bytes(b"old binary") 911 binary.chmod(0o755) 912 _write_ready_vulkan_manifest(artifact_key=artifact_key, pin=pin) 913 old_manifest = artifact_manifest_path(install_dir).read_text(encoding="utf-8") 914 fixture_root = tmp_path / "fixture" / "inner" 915 fixture_root.mkdir(parents=True) 916 (fixture_root / pin["binary_name"]).write_bytes(b"new binary") 917 fixture_tarball = tmp_path / pin["filename"] 918 with tarfile.open(fixture_tarball, "w:gz") as archive: 919 archive.add(fixture_root, arcname="inner") 920 921 def fake_download(_url, dest, **_kwargs): 922 dest.parent.mkdir(parents=True, exist_ok=True) 923 shutil.copy2(fixture_tarball, dest) 924 925 monkeypatch.setattr(local_install, "_download_file", fake_download) 926 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 927 monkeypatch.setattr( 928 local_install, 929 "_write_vulkan_manifest", 930 lambda **_kwargs: (_ for _ in ()).throw(RuntimeError("manifest broke")), 931 ) 932 933 with pytest.raises(RuntimeError, match="manifest broke"): 934 local_install.install_llama_server() 935 936 assert binary.read_bytes() == b"old binary" 937 assert ( 938 artifact_manifest_path(install_dir).read_text(encoding="utf-8") == old_manifest 939 ) 940 941 942def test_install_llama_server_publish_failure_preserves_prior_tree( 943 tmp_path, monkeypatch 944): 945 _init_journal(tmp_path, monkeypatch) 946 artifact_key = local_install.llama_server_artifact_key() 947 pin = local_install.pin_for_current_platform() 948 install_dir = local_install.binary_install_dir(artifact_key, pin) 949 binary = local_install.binary_path_for_pin(artifact_key, pin) 950 binary.parent.mkdir(parents=True, exist_ok=True) 951 binary.write_bytes(b"old binary") 952 binary.chmod(0o755) 953 _write_ready_vulkan_manifest(artifact_key=artifact_key, pin=pin) 954 old_manifest = artifact_manifest_path(install_dir).read_text(encoding="utf-8") 955 fixture_root = tmp_path / "fixture" / "inner" 956 fixture_root.mkdir(parents=True) 957 (fixture_root / pin["binary_name"]).write_bytes(b"new binary") 958 fixture_tarball = tmp_path / pin["filename"] 959 with tarfile.open(fixture_tarball, "w:gz") as archive: 960 archive.add(fixture_root, arcname="inner") 961 962 def fake_download(_url, dest, **_kwargs): 963 dest.parent.mkdir(parents=True, exist_ok=True) 964 shutil.copy2(fixture_tarball, dest) 965 966 monkeypatch.setattr(local_install, "_download_file", fake_download) 967 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 968 monkeypatch.setattr( 969 local_install, 970 "publish_staged_tree", 971 lambda _staging, _install_dir: (_ for _ in ()).throw( 972 RuntimeError("publish broke") 973 ), 974 ) 975 976 with pytest.raises(RuntimeError, match="publish broke"): 977 local_install.install_llama_server() 978 979 assert binary.read_bytes() == b"old binary" 980 assert ( 981 artifact_manifest_path(install_dir).read_text(encoding="utf-8") == old_manifest 982 ) 983 984 985def test_install_llama_server_writes_canonical_sequence(tmp_path, monkeypatch): 986 _init_journal(tmp_path, monkeypatch) 987 pin = { 988 "release_tag": "v1", 989 "filename": "llama.tar.gz", 990 "sha256": "abc123", 991 "binary_name": "llama-server", 992 } 993 final_path = local_install.binary_path_for_pin("test-platform", pin) 994 final_path.parent.mkdir(parents=True) 995 final_path.write_text("binary", encoding="utf-8") 996 observed: list[tuple[str, str]] = [] 997 998 monkeypatch.setattr( 999 local_install, "llama_server_artifact_key", lambda: "test-platform" 1000 ) 1001 monkeypatch.setattr(local_install, "pin_for_current_platform", lambda: pin) 1002 1003 def fake_download(_url, _dest, **_kwargs): 1004 observed.append(("download", _local_status()["install_state"])) 1005 _dest.parent.mkdir(parents=True, exist_ok=True) 1006 _dest.write_bytes(b"artifact") 1007 _dest.parent.mkdir(parents=True, exist_ok=True) 1008 _dest.write_bytes(b"artifact") 1009 1010 def fake_verify(_path, _expected): 1011 observed.append(("verify", _local_status()["install_state"])) 1012 1013 monkeypatch.setattr(local_install, "_download_file", fake_download) 1014 monkeypatch.setattr(local_install, "_verify_sha256", fake_verify) 1015 monkeypatch.setattr( 1016 local_install, "_safe_extract_tarball", lambda _tarball, _dest: None 1017 ) 1018 monkeypatch.setattr( 1019 local_install, "_find_extracted_binary", lambda _dest, _name: final_path 1020 ) 1021 monkeypatch.setattr(local_install, "_chmod_executable", lambda _path: None) 1022 monkeypatch.setattr(local_install, "_clear_macos_quarantine", lambda _path: None) 1023 1024 result = local_install.install_llama_server() 1025 1026 assert [entry[0] for entry in observed] == ["download", "verify"] 1027 assert observed[0][1] == "downloading" 1028 assert observed[1][1] == "verifying" 1029 assert result["install_state"] == "verifying" 1030 assert prove_manifest( 1031 artifact_manifest_path(final_path.parent), 1032 provider=local_install.LOCAL_PROVIDER_NAME, 1033 pin_identity=local_install._vulkan_pin_identity("test-platform", pin), 1034 ).ready 1035 1036 1037@pytest.mark.parametrize( 1038 ("machine", "arch", "expected_cpu", "unexpected_cpu"), 1039 [ 1040 ("x86_64", "amd64", "libggml-cpu-haswell.so", "libggml-cpu-armv8.0_1.so"), 1041 ("arm64", "arm64", "libggml-cpu-armv8.0_1.so", "libggml-cpu-haswell.so"), 1042 ], 1043) 1044def test_install_llama_server_cuda_extracts_flat_tarball_and_writes_manifest( 1045 tmp_path, 1046 monkeypatch, 1047 machine: str, 1048 arch: str, 1049 expected_cpu: str, 1050 unexpected_cpu: str, 1051): 1052 _init_journal(tmp_path, monkeypatch) 1053 monkeypatch.setattr(local_install.platform, "machine", lambda: machine) 1054 _force_cuda_backend(monkeypatch) 1055 tarball = _write_cuda_runtime_tarball(tmp_path, arch=arch) 1056 _patch_tarball_download(monkeypatch, tarball) 1057 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 1058 1059 result = local_install.install_llama_server() 1060 1061 wanted_files = local_install.CUDA_SERVER_PIN.wanted_files_for_arch(arch) 1062 assert result["install_state"] == "verifying" 1063 assert expected_cpu in wanted_files 1064 assert unexpected_cpu not in wanted_files 1065 for name in wanted_files: 1066 assert (local_install.cuda_binary_dir() / name).is_file() 1067 assert (local_install.cuda_binary_dir() / "licenses" / "LICENSE").is_file() 1068 assert (local_install.cuda_binary_dir() / "provenance.json").is_file() 1069 assert not (local_install.cuda_binary_dir() / ".oci-install.json").exists() 1070 assert local_install.cuda_binary_path().stat().st_mode & 0o111 1071 1072 artifact_pin = local_install.require_cuda_artifact_pin_for_current_platform() 1073 proof = prove_manifest( 1074 artifact_manifest_path(local_install.cuda_binary_dir()), 1075 provider=local_install.LOCAL_PROVIDER_NAME, 1076 pin_identity=local_install._cuda_pin_identity( 1077 arch, 1078 wanted_files, 1079 artifact_pin=artifact_pin, 1080 ), 1081 ) 1082 assert proof.ready 1083 manifest = json.loads( 1084 artifact_manifest_path(local_install.cuda_binary_dir()).read_text( 1085 encoding="utf-8" 1086 ) 1087 ) 1088 inventory_paths = {entry["relative_path"] for entry in manifest["inventory"]} 1089 assert set(wanted_files) <= inventory_paths 1090 assert {"licenses/LICENSE", "provenance.json"} <= inventory_paths 1091 1092 1093def test_install_llama_server_cuda_sha256_mismatch_fails_closed(tmp_path, monkeypatch): 1094 _init_journal(tmp_path, monkeypatch) 1095 _force_cuda_backend(monkeypatch) 1096 tarball = _write_cuda_runtime_tarball(tmp_path) 1097 _patch_tarball_download(monkeypatch, tarball) 1098 1099 with pytest.raises(local_install.LocalProviderError) as exc_info: 1100 local_install.install_llama_server() 1101 1102 assert exc_info.value.reason_code == "sha256_mismatch" 1103 status = _local_status() 1104 assert status["install_state"] == "failed" 1105 assert status["error_code"] == "sha256_mismatch" 1106 assert not local_install.cuda_binary_dir().exists() 1107 1108 1109@pytest.mark.parametrize( 1110 ("missing", "expected_detail"), 1111 [ 1112 (("libllama.so.0",), "libllama.so.0"), 1113 (("licenses/",), "licenses/"), 1114 ], 1115) 1116def test_install_llama_server_cuda_required_files_fail_closed( 1117 tmp_path, 1118 monkeypatch, 1119 missing: tuple[str, ...], 1120 expected_detail: str, 1121): 1122 _init_journal(tmp_path, monkeypatch) 1123 _force_cuda_backend(monkeypatch) 1124 tarball = _write_cuda_runtime_tarball(tmp_path, missing=missing) 1125 _patch_tarball_download(monkeypatch, tarball) 1126 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 1127 1128 with pytest.raises(local_install.LocalProviderError) as exc_info: 1129 local_install.install_llama_server() 1130 1131 assert exc_info.value.reason_code == "cuda_runtime_incomplete" 1132 assert expected_detail in str(exc_info.value) 1133 assert not local_install.cuda_binary_dir().exists() 1134 1135 1136def test_install_llama_server_cuda_rejects_traversal_member(tmp_path, monkeypatch): 1137 _init_journal(tmp_path, monkeypatch) 1138 _force_cuda_backend(monkeypatch) 1139 tarball = _write_cuda_runtime_tarball(tmp_path, traversal=True) 1140 _patch_tarball_download(monkeypatch, tarball) 1141 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 1142 1143 with pytest.raises(local_install.LocalProviderError) as exc_info: 1144 local_install.install_llama_server() 1145 1146 assert exc_info.value.reason_code == "archive_path_traversal" 1147 assert not (tmp_path / "escape").exists() 1148 assert not local_install.cuda_binary_dir().exists() 1149 1150 1151def test_install_llama_server_cuda_removes_legacy_oci_tree_after_publish_only( 1152 tmp_path, 1153 monkeypatch, 1154): 1155 _init_journal(tmp_path, monkeypatch) 1156 _force_cuda_backend(monkeypatch) 1157 artifact_key = local_install.llama_server_artifact_key() 1158 legacy_digest = "a" * 64 1159 legacy_dir = ( 1160 tmp_path 1161 / "cache" 1162 / "providers" 1163 / "local" 1164 / "cuda" 1165 / artifact_key 1166 / legacy_digest 1167 ) 1168 legacy_dir.mkdir(parents=True) 1169 (legacy_dir / ".oci-install.json").write_text( 1170 json.dumps( 1171 { 1172 "image_ref": f"ghcr.io/acme/runtime@sha256:{legacy_digest}", 1173 "arch": "amd64", 1174 "files": {"llama-server": "b" * 64}, 1175 } 1176 ) 1177 + "\n", 1178 encoding="utf-8", 1179 ) 1180 (legacy_dir / "llama-server").write_text("legacy", encoding="utf-8") 1181 vulkan_dir = local_install.binary_install_dir() 1182 vulkan_dir.mkdir(parents=True) 1183 (vulkan_dir / "llama-server").write_text("vulkan", encoding="utf-8") 1184 tarball = _write_cuda_runtime_tarball(tmp_path) 1185 _patch_tarball_download(monkeypatch, tarball) 1186 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 1187 1188 local_install.install_llama_server() 1189 1190 assert not legacy_dir.exists() 1191 assert (vulkan_dir / "llama-server").read_text(encoding="utf-8") == "vulkan" 1192 assert local_install.cuda_binary_path().is_file() 1193 1194 1195def test_install_llama_server_cuda_failure_leaves_legacy_oci_tree( 1196 tmp_path, 1197 monkeypatch, 1198): 1199 _init_journal(tmp_path, monkeypatch) 1200 _force_cuda_backend(monkeypatch) 1201 artifact_key = local_install.llama_server_artifact_key() 1202 legacy_digest = "a" * 64 1203 legacy_dir = ( 1204 tmp_path 1205 / "cache" 1206 / "providers" 1207 / "local" 1208 / "cuda" 1209 / artifact_key 1210 / legacy_digest 1211 ) 1212 legacy_dir.mkdir(parents=True) 1213 (legacy_dir / ".oci-install.json").write_text( 1214 json.dumps( 1215 { 1216 "image_ref": f"ghcr.io/acme/runtime@sha256:{legacy_digest}", 1217 "arch": "amd64", 1218 "files": {"llama-server": "b" * 64}, 1219 } 1220 ) 1221 + "\n", 1222 encoding="utf-8", 1223 ) 1224 tarball = _write_cuda_runtime_tarball(tmp_path, missing=("licenses/",)) 1225 _patch_tarball_download(monkeypatch, tarball) 1226 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 1227 1228 with pytest.raises(local_install.LocalProviderError): 1229 local_install.install_llama_server() 1230 1231 assert legacy_dir.exists() 1232 1233 1234def test_install_llama_server_cuda_preserves_partial_legacy_oci_sidecar( 1235 tmp_path, 1236 monkeypatch, 1237) -> None: 1238 _init_journal(tmp_path, monkeypatch) 1239 _force_cuda_backend(monkeypatch) 1240 artifact_key = local_install.llama_server_artifact_key() 1241 legacy_digest = "a" * 64 1242 legacy_dir = ( 1243 tmp_path 1244 / "cache" 1245 / "providers" 1246 / "local" 1247 / "cuda" 1248 / artifact_key 1249 / legacy_digest 1250 ) 1251 legacy_dir.mkdir(parents=True) 1252 (legacy_dir / ".oci-install.json").write_text( 1253 json.dumps( 1254 { 1255 "image_ref": f"ghcr.io/acme/runtime@sha256:{legacy_digest}", 1256 "files": {"llama-server": "b" * 64}, 1257 } 1258 ) 1259 + "\n", 1260 encoding="utf-8", 1261 ) 1262 tarball = _write_cuda_runtime_tarball(tmp_path) 1263 _patch_tarball_download(monkeypatch, tarball) 1264 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 1265 1266 local_install.install_llama_server() 1267 1268 assert legacy_dir.exists() 1269 assert local_install.cuda_binary_path().is_file() 1270 1271 1272def test_install_llama_server_cuda_cleanup_failure_does_not_fail_published_install( 1273 tmp_path, 1274 monkeypatch, 1275) -> None: 1276 _init_journal(tmp_path, monkeypatch) 1277 _force_cuda_backend(monkeypatch) 1278 tarball = _write_cuda_runtime_tarball(tmp_path) 1279 _patch_tarball_download(monkeypatch, tarball) 1280 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 1281 real_publish = local_install.publish_staged_tree 1282 real_resolve = Path.resolve 1283 1284 def publish_and_break_cleanup(staging: Path, target: Path) -> None: 1285 real_publish(staging, target) 1286 1287 def fail_target_resolve(path: Path, *args: object, **kwargs: object) -> Path: 1288 if path == target: 1289 raise OSError("resolve failed") 1290 return real_resolve(path, *args, **kwargs) 1291 1292 monkeypatch.setattr(Path, "resolve", fail_target_resolve) 1293 1294 monkeypatch.setattr(local_install, "publish_staged_tree", publish_and_break_cleanup) 1295 1296 result = local_install.install_llama_server() 1297 1298 assert result["install_state"] == "verifying" 1299 assert _local_status()["install_state"] == "verifying" 1300 assert local_install.cuda_binary_path().is_file() 1301 1302 1303@pytest.mark.parametrize("flow", ["llama_server", "model", "install_local"]) 1304def test_local_install_owner_paths_have_no_oci_registry_or_cosign_entrypoint( 1305 tmp_path, 1306 monkeypatch, 1307 flow: str, 1308) -> None: 1309 source = Path(local_install.__file__).read_text(encoding="utf-8") 1310 assert "solstone.think.providers import oci_image" not in source 1311 assert "pull_and_install" not in source 1312 assert "verify_image_signature" not in source 1313 assert "cosign" not in source 1314 1315 def reject_oci_registry_url(url: object) -> None: 1316 parsed = urlparse(str(url)) 1317 if ( 1318 parsed.hostname == "ghcr.io" 1319 or parsed.path.startswith("/v2/") 1320 or "scope=repository:" in parsed.query 1321 ): 1322 raise AssertionError(f"OCI registry access must not run: {url}") 1323 1324 def fail_cosign(cmd: list[str], **_kwargs: object) -> SimpleNamespace: 1325 if cmd and cmd[0] == "cosign": 1326 raise AssertionError("cosign must not run in the owner install path") 1327 return SimpleNamespace(returncode=0, stdout="", stderr="") 1328 1329 class RegistryTrapClient: 1330 def __init__(self, *_args: object, **_kwargs: object) -> None: 1331 pass 1332 1333 def __enter__(self) -> RegistryTrapClient: 1334 return self 1335 1336 def __exit__(self, *_args: object) -> None: 1337 return None 1338 1339 def get(self, url: object, *_args: object, **_kwargs: object) -> object: 1340 reject_oci_registry_url(url) 1341 raise AssertionError(f"unexpected httpx.Client.get during install: {url}") 1342 1343 def stream( 1344 self, _method: str, url: object, *_args: object, **_kwargs: object 1345 ) -> object: 1346 reject_oci_registry_url(url) 1347 raise AssertionError( 1348 f"unexpected httpx.Client.stream during install: {url}" 1349 ) 1350 1351 def fail_httpx_stream( 1352 _method: str, url: object, *_args: object, **_kwargs: object 1353 ) -> object: 1354 reject_oci_registry_url(url) 1355 raise AssertionError(f"unexpected live httpx.stream during install: {url}") 1356 1357 _init_journal(tmp_path, monkeypatch) 1358 _force_cuda_backend(monkeypatch) 1359 tarball = _write_cuda_runtime_tarball(tmp_path) 1360 1361 def fake_download(url: str, dest: Path, **kwargs: object) -> None: 1362 reject_oci_registry_url(url) 1363 dest.parent.mkdir(parents=True, exist_ok=True) 1364 if dest.name.endswith(".tar.gz"): 1365 shutil.copyfile(tarball, dest) 1366 else: 1367 dest.write_text(dest.name, encoding="utf-8") 1368 on_progress = kwargs.get("on_progress") 1369 if on_progress is not None: 1370 on_progress(dest.stat().st_size, dest.stat().st_size) 1371 1372 monkeypatch.setattr(local_install, "_download_file", fake_download) 1373 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 1374 monkeypatch.setattr(subprocess, "run", fail_cosign) 1375 monkeypatch.setattr("httpx.Client", RegistryTrapClient) 1376 monkeypatch.setattr("httpx.stream", fail_httpx_stream) 1377 monkeypatch.setattr( 1378 fit_report, "build_local_fit_report", lambda _model_id: _fit("ok") 1379 ) 1380 1381 if flow == "llama_server": 1382 local_install.install_llama_server() 1383 elif flow == "model": 1384 local_install.install_model(LOCAL_MODEL) 1385 else: 1386 readiness_calls = 0 1387 1388 def fake_readiness(model_id: str) -> ReadinessOutcome: 1389 nonlocal readiness_calls 1390 readiness_calls += 1 1391 return _fake_local_readiness( 1392 binary_installed=readiness_calls > 1, 1393 model_installed=readiness_calls > 1, 1394 binary_path=local_install.cuda_binary_path(), 1395 model_path=local_install.model_path(model_id), 1396 mmproj_path=local_install.mmproj_path(model_id), 1397 backend="cuda", 1398 backend_reason="test cuda", 1399 ) 1400 1401 monkeypatch.setattr(local_install, "inspect_readiness", fake_readiness) 1402 local_install.install_local(LOCAL_MODEL) 1403 1404 1405def test_probe_binary_runnable_returns_true_for_zero_exit(tmp_path): 1406 script = _write_probe_script(tmp_path, "exit 0") 1407 1408 assert local_install.probe_binary_runnable(script) == (True, None) 1409 1410 1411def test_probe_binary_runnable_returns_verbatim_loader_stderr(tmp_path): 1412 detail = "dyld: Library not loaded: @rpath/libfoo.dylib" 1413 script = _write_probe_script(tmp_path, f"echo '{detail}' >&2\nexit 1") 1414 1415 runnable, error = local_install.probe_binary_runnable(script) 1416 1417 assert runnable is False 1418 assert error == detail 1419 1420 1421def test_probe_binary_runnable_returns_verbatim_non_loader_stderr(tmp_path): 1422 detail = "plain launch failure" 1423 script = _write_probe_script(tmp_path, f"echo '{detail}' >&2\nexit 2") 1424 1425 runnable, error = local_install.probe_binary_runnable(script) 1426 1427 assert runnable is False 1428 assert error == detail 1429 1430 1431def test_probe_binary_runnable_uses_stdout_when_stderr_empty(tmp_path): 1432 detail = "stdout launch failure" 1433 script = _write_probe_script(tmp_path, f"echo '{detail}'\nexit 3") 1434 1435 runnable, error = local_install.probe_binary_runnable(script) 1436 1437 assert runnable is False 1438 assert error == detail 1439 1440 1441def test_probe_binary_runnable_times_out(tmp_path, monkeypatch): 1442 script = _write_probe_script(tmp_path, "sleep 5") 1443 monkeypatch.setattr(local_install, "_PROBE_TIMEOUT_SECONDS", 0.5) 1444 1445 started_at = time.monotonic() 1446 runnable, error = local_install.probe_binary_runnable(script) 1447 1448 assert time.monotonic() - started_at < 2 1449 assert runnable is False 1450 assert error is not None 1451 assert error.startswith("timed out") 1452 1453 1454def test_probe_binary_runnable_handles_missing_path(tmp_path): 1455 runnable, error = local_install.probe_binary_runnable(tmp_path / "missing") 1456 1457 assert runnable is False 1458 assert error 1459 1460 1461def test_install_model_writes_canonical_sequence(tmp_path, monkeypatch): 1462 _init_journal(tmp_path, monkeypatch) 1463 spec = LOCAL_MODEL_SPECS[LOCAL_MODEL] 1464 observed: list[tuple[str, str]] = [] 1465 1466 def fake_download(_url, _dest, **_kwargs): 1467 observed.append(("download", _local_status()["install_state"])) 1468 _dest.parent.mkdir(parents=True, exist_ok=True) 1469 _dest.write_bytes(b"artifact") 1470 1471 def fake_verify(_path, _expected): 1472 observed.append(("verify", _local_status()["install_state"])) 1473 1474 monkeypatch.setattr(local_install, "_download_file", fake_download) 1475 monkeypatch.setattr(local_install, "_verify_sha256", fake_verify) 1476 1477 result = local_install.install_model(LOCAL_MODEL) 1478 1479 assert [entry[0] for entry in observed] == [ 1480 "download", 1481 "download", 1482 "verify", 1483 "verify", 1484 ] 1485 assert observed[0][1] == "downloading" 1486 assert observed[2][1] == "verifying" 1487 assert result["install_state"] == "verifying" 1488 assert prove_manifest( 1489 artifact_manifest_path(local_install.model_dir(spec.model_id)), 1490 provider=local_install.LOCAL_PROVIDER_NAME, 1491 pin_identity=local_install._model_pin_identity(spec.model_id), 1492 ).ready 1493 1494 1495def test_install_model_threads_optional_mmproj_artifact(tmp_path, monkeypatch): 1496 _init_journal(tmp_path, monkeypatch) 1497 spec = replace( 1498 LOCAL_MODEL_SPECS[LOCAL_MODEL], 1499 mmproj_filename="mmproj-test.gguf", 1500 mmproj_sha256="mmproj-sha", 1501 ) 1502 downloads: list[Path] = [] 1503 verifies: list[tuple[Path, str]] = [] 1504 1505 monkeypatch.setitem(local_install.LOCAL_MODEL_SPECS, LOCAL_MODEL, spec) 1506 1507 def fake_download(_url, dest, **_kwargs): 1508 downloads.append(dest) 1509 dest.parent.mkdir(parents=True, exist_ok=True) 1510 dest.write_bytes(b"artifact") 1511 1512 def fake_verify(path, expected): 1513 verifies.append((path, expected)) 1514 1515 monkeypatch.setattr(local_install, "_download_file", fake_download) 1516 monkeypatch.setattr(local_install, "_verify_sha256", fake_verify) 1517 1518 local_install.install_model(LOCAL_MODEL) 1519 1520 gguf_path = local_install.model_path(LOCAL_MODEL) 1521 mmproj_path = local_install.mmproj_path(LOCAL_MODEL) 1522 assert mmproj_path is not None 1523 assert downloads == [gguf_path, mmproj_path] 1524 assert verifies == [(gguf_path, spec.sha256), (mmproj_path, "mmproj-sha")] 1525 assert prove_manifest( 1526 artifact_manifest_path(local_install.model_dir(LOCAL_MODEL)), 1527 provider=local_install.LOCAL_PROVIDER_NAME, 1528 pin_identity=local_install._model_pin_identity(LOCAL_MODEL), 1529 ).ready 1530 1531 1532def test_install_local_blocks_before_downloads(tmp_path, monkeypatch): 1533 _init_journal(tmp_path, monkeypatch) 1534 monkeypatch.setattr( 1535 local_install, 1536 "inspect_readiness", 1537 lambda model_id: _fake_local_readiness( 1538 binary_installed=False, 1539 model_installed=False, 1540 binary_path=tmp_path / "llama-server", 1541 model_path=tmp_path / "model.gguf", 1542 ), 1543 ) 1544 monkeypatch.setattr( 1545 fit_report, "build_local_fit_report", lambda model_id: _fit("blocked") 1546 ) 1547 monkeypatch.setattr( 1548 local_install, 1549 "_download_file", 1550 lambda *_args, **_kwargs: pytest.fail("download should not start"), 1551 ) 1552 1553 with pytest.raises(local_install.LocalProviderError) as exc_info: 1554 local_install.install_local(LOCAL_MODEL) 1555 1556 assert exc_info.value.reason_code == "host_unfit" 1557 1558 1559def test_install_local_warning_continues_to_download(tmp_path, monkeypatch): 1560 _init_journal(tmp_path, monkeypatch) 1561 pin = { 1562 "release_tag": "v1", 1563 "filename": "llama.tar.gz", 1564 "sha256": "abc123", 1565 "binary_name": "llama-server", 1566 } 1567 final_path = local_install.binary_path_for_pin("test-platform", pin) 1568 final_path.parent.mkdir(parents=True) 1569 final_path.write_text("binary", encoding="utf-8") 1570 downloads: list[Path] = [] 1571 readiness_calls = 0 1572 1573 def fake_readiness(model_id: str) -> ReadinessOutcome: 1574 nonlocal readiness_calls 1575 readiness_calls += 1 1576 return _fake_local_readiness( 1577 binary_installed=readiness_calls > 1, 1578 model_installed=readiness_calls > 1, 1579 binary_path=final_path, 1580 model_path=local_install.model_path(model_id), 1581 mmproj_path=local_install.mmproj_path(model_id), 1582 ) 1583 1584 monkeypatch.setattr(local_install, "inspect_readiness", fake_readiness) 1585 monkeypatch.setattr( 1586 fit_report, "build_local_fit_report", lambda model_id: _fit("warning") 1587 ) 1588 monkeypatch.setattr( 1589 local_install, "llama_server_artifact_key", lambda: "test-platform" 1590 ) 1591 monkeypatch.setattr(local_install, "pin_for_current_platform", lambda: pin) 1592 1593 def fake_download(_url, dest, **_kwargs): 1594 downloads.append(dest) 1595 dest.parent.mkdir(parents=True, exist_ok=True) 1596 dest.write_bytes(b"artifact") 1597 1598 monkeypatch.setattr(local_install, "_download_file", fake_download) 1599 monkeypatch.setattr(local_install, "_verify_sha256", lambda _path, _expected: None) 1600 monkeypatch.setattr( 1601 local_install, "_safe_extract_tarball", lambda _tarball, _dest: None 1602 ) 1603 monkeypatch.setattr( 1604 local_install, "_find_extracted_binary", lambda _dest, _name: final_path 1605 ) 1606 monkeypatch.setattr(local_install, "_chmod_executable", lambda _path: None) 1607 monkeypatch.setattr(local_install, "_clear_macos_quarantine", lambda _path: None) 1608 1609 assert local_install.install_local(LOCAL_MODEL)["install_state"] == "installed" 1610 1611 assert downloads 1612 1613 1614def test_install_local_ready_short_circuits_before_fit_report(tmp_path, monkeypatch): 1615 _init_journal(tmp_path, monkeypatch) 1616 monkeypatch.setattr( 1617 local_install, 1618 "inspect_readiness", 1619 lambda model_id: _fake_local_readiness( 1620 binary_installed=True, 1621 model_installed=True, 1622 binary_path=tmp_path / "llama-server", 1623 model_path=tmp_path / "model.gguf", 1624 ), 1625 ) 1626 monkeypatch.setattr( 1627 fit_report, 1628 "build_local_fit_report", 1629 lambda model_id: pytest.fail("fit report should not run"), 1630 ) 1631 monkeypatch.setattr( 1632 local_install, 1633 "_download_file", 1634 lambda *_args, **_kwargs: pytest.fail("download should not start"), 1635 ) 1636 1637 result = local_install.install_local(LOCAL_MODEL) 1638 1639 assert result["provider"] == local_install.LOCAL_PROVIDER_NAME 1640 assert result["install_state"] == "installed" 1641 1642 1643def test_install_local_reinstalls_runtime_when_binary_record_stale( 1644 tmp_path, monkeypatch 1645): 1646 _init_journal(tmp_path, monkeypatch) 1647 gguf = local_install.model_path(LOCAL_MODEL) 1648 gguf.parent.mkdir(parents=True, exist_ok=True) 1649 gguf.write_text("qwen", encoding="utf-8") 1650 mmproj = local_install.mmproj_path(LOCAL_MODEL) 1651 assert mmproj is not None 1652 mmproj.write_text("mmproj", encoding="utf-8") 1653 monkeypatch.setattr(local_vulkan, "detect_gpus", lambda: []) 1654 monkeypatch.setattr( 1655 fit_report, "build_local_fit_report", lambda model_id: _fit("ok") 1656 ) 1657 calls: list[str] = [] 1658 readiness_calls = 0 1659 1660 def fake_readiness(model_id: str) -> ReadinessOutcome: 1661 nonlocal readiness_calls 1662 readiness_calls += 1 1663 return _fake_local_readiness( 1664 binary_installed=readiness_calls > 1, 1665 model_installed=readiness_calls > 1, 1666 binary_path=local_install.binary_path_for_pin(), 1667 model_path=local_install.model_path(model_id), 1668 mmproj_path=local_install.mmproj_path(model_id), 1669 ) 1670 1671 def fake_install_llama_server(**_kwargs): 1672 calls.append("llama_server") 1673 return {"install_state": "verifying"} 1674 1675 def fake_install_model(model_id: str, **_kwargs): 1676 calls.append("model") 1677 return {"install_state": "verifying", "model_id": model_id} 1678 1679 monkeypatch.setattr(local_install, "inspect_readiness", fake_readiness) 1680 monkeypatch.setattr( 1681 local_install, "install_llama_server", fake_install_llama_server 1682 ) 1683 monkeypatch.setattr(local_install, "install_model", fake_install_model) 1684 1685 result = local_install.install_local(LOCAL_MODEL) 1686 1687 assert result["install_state"] == "installed" 1688 assert calls == ["llama_server", "model"] 1689 1690 1691def test_install_local_replaces_failed_cuda_attempt_with_current_cuda_target( 1692 tmp_path: Path, 1693 monkeypatch: pytest.MonkeyPatch, 1694) -> None: 1695 _init_journal(tmp_path, monkeypatch) 1696 _patch_backend_inputs( 1697 monkeypatch, 1698 compute_cap="sm_89", 1699 driver_cuda_version=15, 1700 trust=local_cuda.ArtifactTrust.TRUSTED, 1701 ) 1702 stale_cuda = { 1703 "provider": "local", 1704 "runtime": "llama.cpp", 1705 "backend": "cuda", 1706 "backend_reason": "old cuda", 1707 "runtime_pin": local_install._cuda_pin_identity(), 1708 "model_pin": local_install._model_pin_identity(LOCAL_MODEL), 1709 } 1710 stale_status = begin_or_replace_install_attempt( 1711 "local", 1712 stale_cuda, 1713 initial_state="resolving", 1714 ) 1715 write_install_status( 1716 transition_state( 1717 stale_status, 1718 new_state="failed", 1719 error="the pinned image has no matching signature", 1720 error_code="signature_verify_failed", 1721 ) 1722 ) 1723 stale_sha = fingerprint_sha256(canonical_fingerprint(stale_cuda)) 1724 monkeypatch.setattr( 1725 fit_report, 1726 "build_local_fit_report", 1727 lambda model_id: _fit("ok"), 1728 ) 1729 calls: list[str] = [] 1730 readiness_calls = 0 1731 1732 def fake_readiness(model_id: str) -> ReadinessOutcome: 1733 nonlocal readiness_calls 1734 readiness_calls += 1 1735 return _fake_local_readiness( 1736 binary_installed=readiness_calls > 1, 1737 model_installed=readiness_calls > 1, 1738 binary_path=local_install.binary_path_for_pin(), 1739 model_path=local_install.model_path(model_id), 1740 mmproj_path=local_install.mmproj_path(model_id), 1741 ) 1742 1743 def fake_install_llama_server(**_kwargs): 1744 calls.append("llama_server") 1745 return {"install_state": "verifying"} 1746 1747 def fake_install_model(model_id: str, **_kwargs): 1748 calls.append("model") 1749 return {"install_state": "verifying", "model_id": model_id} 1750 1751 monkeypatch.setattr(local_install, "inspect_readiness", fake_readiness) 1752 monkeypatch.setattr( 1753 local_install, 1754 "install_llama_server", 1755 fake_install_llama_server, 1756 ) 1757 monkeypatch.setattr(local_install, "install_model", fake_install_model) 1758 1759 result = local_install.install_local(LOCAL_MODEL) 1760 1761 status = _local_status() 1762 target = json.loads(str(status["target_fingerprint_json"])) 1763 assert result["install_state"] == "installed" 1764 assert status["target_fingerprint_sha256"] != stale_sha 1765 assert target["backend"] == "cuda" 1766 assert target["backend_reason"] == "compute_cap sm_89 covered; driver CUDA 15 >= 13" 1767 assert calls == ["llama_server", "model"] 1768 1769 1770def test_ensure_artifacts_installed_returns_binary_gguf_and_optional_mmproj( 1771 tmp_path, monkeypatch 1772): 1773 binary = tmp_path / "llama-server" 1774 gguf = tmp_path / "model.gguf" 1775 mmproj = tmp_path / "mmproj.gguf" 1776 monkeypatch.setattr( 1777 local_install, 1778 "inspect_readiness", 1779 lambda model_id: _fake_local_readiness( 1780 binary_installed=True, 1781 model_installed=True, 1782 binary_path=binary, 1783 model_path=gguf, 1784 mmproj_path=mmproj, 1785 backend="vulkan", 1786 backend_reason="test vulkan", 1787 ), 1788 ) 1789 1790 assert local_install.ensure_artifacts_installed( 1791 LOCAL_MODEL 1792 ) == local_install.LocalArtifacts( 1793 backend="vulkan", 1794 backend_reason="test vulkan", 1795 binary_path=binary, 1796 lib_dir=None, 1797 gguf_path=gguf, 1798 mmproj_path=mmproj, 1799 ) 1800 1801 1802def test_ensure_artifacts_installed_ignores_low_memory_when_artifacts_exist( 1803 tmp_path, monkeypatch 1804): 1805 binary = tmp_path / "llama-server" 1806 gguf = tmp_path / "model.gguf" 1807 monkeypatch.setattr( 1808 local_install, 1809 "inspect_readiness", 1810 lambda model_id: _fake_local_readiness( 1811 binary_installed=True, 1812 model_installed=True, 1813 binary_path=binary, 1814 model_path=gguf, 1815 ram_sufficient=False, 1816 backend="vulkan", 1817 backend_reason="test vulkan", 1818 ), 1819 ) 1820 1821 assert local_install.ensure_artifacts_installed( 1822 LOCAL_MODEL 1823 ) == local_install.LocalArtifacts( 1824 backend="vulkan", 1825 backend_reason="test vulkan", 1826 binary_path=binary, 1827 lib_dir=None, 1828 gguf_path=gguf, 1829 mmproj_path=None, 1830 ) 1831 1832 1833def test_ensure_artifacts_installed_returns_cuda_lib_dir(tmp_path, monkeypatch): 1834 _init_journal(tmp_path, monkeypatch) 1835 binary = tmp_path / "llama-server" 1836 gguf = tmp_path / "model.gguf" 1837 monkeypatch.setattr( 1838 local_install, 1839 "inspect_readiness", 1840 lambda model_id: _fake_local_readiness( 1841 binary_installed=True, 1842 model_installed=True, 1843 binary_path=binary, 1844 model_path=gguf, 1845 backend="cuda", 1846 backend_reason="test cuda", 1847 ), 1848 ) 1849 1850 assert local_install.ensure_artifacts_installed( 1851 LOCAL_MODEL 1852 ) == local_install.LocalArtifacts( 1853 backend="cuda", 1854 backend_reason="test cuda", 1855 binary_path=binary, 1856 lib_dir=local_install.cuda_binary_dir(), 1857 gguf_path=gguf, 1858 mmproj_path=None, 1859 ) 1860 1861 1862@pytest.mark.parametrize( 1863 ("binary_installed", "model_installed", "reason_code"), 1864 [(False, True, "binary_missing"), (True, False, "model_missing")], 1865) 1866def test_ensure_artifacts_installed_raises_for_missing_artifacts( 1867 tmp_path, 1868 monkeypatch, 1869 binary_installed, 1870 model_installed, 1871 reason_code, 1872): 1873 binary = tmp_path / "llama-server" 1874 gguf = tmp_path / "model.gguf" 1875 monkeypatch.setattr( 1876 local_install, 1877 "inspect_readiness", 1878 lambda model_id: _fake_local_readiness( 1879 binary_installed=binary_installed, 1880 model_installed=model_installed, 1881 binary_path=binary, 1882 model_path=gguf, 1883 ), 1884 ) 1885 1886 with pytest.raises(local_install.LocalProviderError) as exc_info: 1887 local_install.ensure_artifacts_installed(LOCAL_MODEL) 1888 1889 assert exc_info.value.reason_code == reason_code 1890 1891 1892def test_inspect_readiness_reports_ram_sufficient_for_low_or_unknown_memory( 1893 tmp_path, monkeypatch 1894): 1895 _init_journal(tmp_path, monkeypatch) 1896 monkeypatch.setattr( 1897 memory.psutil, 1898 "virtual_memory", 1899 lambda: SimpleNamespace(available=1 * 1024**3, total=16 * 1024**3), 1900 ) 1901 1902 readiness = local_install.inspect_readiness(LOCAL_MODEL) 1903 1904 assert readiness.host["ram_sufficient"] is True 1905 1906 1907@pytest.mark.parametrize("manifest_ok", [True, False]) 1908def test_inspect_readiness_cuda_uses_manifest_full_set( 1909 tmp_path, 1910 monkeypatch, 1911 manifest_ok, 1912): 1913 _init_journal(tmp_path, monkeypatch) 1914 _force_cuda_backend(monkeypatch) 1915 binary = local_install.cuda_binary_path() 1916 binary.parent.mkdir(parents=True, exist_ok=True) 1917 arch = local_install._cuda_runtime_arch() 1918 wanted_files = local_install.CUDA_SERVER_PIN.wanted_files_for_arch(arch) 1919 for name in wanted_files: 1920 member = binary.parent / name 1921 member.write_text(name, encoding="utf-8") 1922 member.chmod(0o755) 1923 licenses = binary.parent / "licenses" 1924 licenses.mkdir() 1925 (licenses / "LICENSE").write_text("license", encoding="utf-8") 1926 (binary.parent / "provenance.json").write_text("{}\n", encoding="utf-8") 1927 artifact_pin = local_install.require_cuda_artifact_pin_for_current_platform() 1928 local_install._write_cuda_manifest( 1929 artifact_key=local_install.llama_server_artifact_key(), 1930 artifact_pin=artifact_pin, 1931 arch=arch, 1932 wanted_files=wanted_files, 1933 attempt_status=None, 1934 fingerprint=local_install.target_fingerprint(LOCAL_MODEL), 1935 root=binary.parent, 1936 ) 1937 if not manifest_ok: 1938 (binary.parent / wanted_files[-1]).unlink() 1939 monkeypatch.setattr( 1940 local_vulkan, 1941 "detect_gpus", 1942 lambda: (_ for _ in ()).throw( 1943 AssertionError("Vulkan probe not expected for CUDA readiness") 1944 ), 1945 ) 1946 1947 readiness = local_install.inspect_readiness(LOCAL_MODEL) 1948 1949 assert readiness.host["backend"] == "cuda" 1950 assert readiness.host["backend_reason"] == ( 1951 "compute_cap sm_121 covered; driver CUDA 13 >= 13" 1952 ) 1953 assert readiness.artifacts["binary_path"] == str(binary) 1954 assert readiness.artifacts["binary_installed"] is manifest_ok 1955 assert readiness.host["gpu_available"] is True 1956 assert readiness.host["gpu_probe_ok"] is True 1957 assert readiness.proof["cuda"]["status"] == ( 1958 "ready" if manifest_ok else "missing-or-mismatched" 1959 ) 1960 1961 1962def test_inspect_readiness_reports_gpu_available_with_hardware(tmp_path, monkeypatch): 1963 _init_journal(tmp_path, monkeypatch) 1964 monkeypatch.setattr( 1965 local_vulkan, 1966 "detect_gpus", 1967 lambda: [ 1968 local_vulkan.VulkanDevice( 1969 1, 1970 "NVIDIA GeForce GTX 1660 Ti", 1971 local_vulkan.VK_TYPE_DISCRETE, 1972 6390, 1973 ) 1974 ], 1975 ) 1976 1977 readiness = local_install.inspect_readiness(LOCAL_MODEL) 1978 1979 assert readiness.host["gpu_available"] is True 1980 assert readiness.host["backend"] == "vulkan" 1981 assert readiness.host["backend_reason"] == "no NVIDIA GPU detected" 1982 1983 1984def test_inspect_readiness_reports_gpu_unavailable_without_hardware( 1985 tmp_path, monkeypatch 1986): 1987 _init_journal(tmp_path, monkeypatch) 1988 monkeypatch.setattr(local_vulkan, "detect_gpus", lambda: []) 1989 1990 readiness = local_install.inspect_readiness(LOCAL_MODEL) 1991 1992 assert readiness.host["gpu_available"] is False 1993 1994 1995def test_inspect_readiness_stale_non_cuda_binary_record_reports_not_installed( 1996 tmp_path, monkeypatch 1997): 1998 _init_journal(tmp_path, monkeypatch) 1999 monkeypatch.setattr(local_vulkan, "detect_gpus", lambda: []) 2000 canonical = local_install.binary_path_for_pin() 2001 canonical.parent.mkdir(parents=True, exist_ok=True) 2002 canonical.write_bytes(b"llama-server") 2003 canonical.chmod(0o755) 2004 2005 readiness = local_install.inspect_readiness(LOCAL_MODEL) 2006 2007 assert readiness.artifacts["binary_installed"] is False 2008 assert readiness.artifacts["binary_path"] == str(canonical) 2009 assert readiness.proof["binary"]["status"] == "missing-or-mismatched" 2010 2011 2012def test_inspect_readiness_matching_non_cuda_binary_record_reports_installed( 2013 tmp_path, monkeypatch 2014): 2015 _init_journal(tmp_path, monkeypatch) 2016 monkeypatch.setattr(local_vulkan, "detect_gpus", lambda: []) 2017 pin = local_install.pin_for_current_platform() 2018 canonical = local_install.binary_path_for_pin() 2019 canonical.parent.mkdir(parents=True, exist_ok=True) 2020 canonical.write_bytes(b"llama-server") 2021 canonical.chmod(0o755) 2022 _write_ready_vulkan_manifest(pin=pin) 2023 2024 readiness = local_install.inspect_readiness(LOCAL_MODEL) 2025 2026 assert readiness.artifacts["binary_installed"] is True 2027 2028 2029def test_inspect_readiness_honors_vulkan_device_override(tmp_path, monkeypatch): 2030 _init_journal(tmp_path, monkeypatch) 2031 devices = [ 2032 local_vulkan.VulkanDevice( 2033 0, 2034 "Intel(R) Graphics", 2035 local_vulkan.VK_TYPE_INTEGRATED, 2036 23814, 2037 ), 2038 local_vulkan.VulkanDevice( 2039 1, 2040 "llvmpipe (LLVM)", 2041 local_vulkan.VK_TYPE_CPU, 2042 0, 2043 ), 2044 ] 2045 monkeypatch.setattr(local_vulkan, "detect_gpus", lambda: devices) 2046 _write_provider_local_config(tmp_path, {"vulkan_device_index": "0"}) 2047 2048 assert local_install.gpu_device_override() == 0 2049 assert resolve_local_endpoint().is_bundled is True 2050 assert local_install.inspect_readiness(LOCAL_MODEL).host["gpu_available"] is True 2051 2052 _write_provider_local_config(tmp_path, {"vulkan_device_index": "1"}) 2053 2054 assert local_install.inspect_readiness(LOCAL_MODEL).host["gpu_available"] is False 2055 2056 2057def test_inspect_readiness_ignores_stale_model_path_after_model_change( 2058 tmp_path, monkeypatch 2059): 2060 # A record left by a prior model's install (different model_id, gguf under a 2061 # different model dir) must NOT be trusted: a LOCAL_MODEL change without a 2062 # reinstall would otherwise pair the stale gguf with the new model's mmproj 2063 # and abort llama-server with an n_embd text/projector mismatch. Readiness 2064 # recomputes both artifact paths from the selected model's spec. 2065 _init_journal(tmp_path, monkeypatch) 2066 stale_dir = local_install.model_dir("local/old-coder-7b") 2067 stale_dir.mkdir(parents=True, exist_ok=True) 2068 stale_gguf = stale_dir / "coder-7b-Q4_K_M.gguf" 2069 stale_gguf.write_text("stale", encoding="utf-8") 2070 2071 # Stage the selected model's artifacts in its own directory. 2072 gguf = local_install.model_path(LOCAL_MODEL) 2073 gguf.parent.mkdir(parents=True, exist_ok=True) 2074 gguf.write_text("qwen", encoding="utf-8") 2075 mmproj = local_install.mmproj_path(LOCAL_MODEL) 2076 assert mmproj is not None 2077 mmproj.write_text("mmproj", encoding="utf-8") 2078 _write_ready_model_manifest(LOCAL_MODEL) 2079 2080 readiness = local_install.inspect_readiness(LOCAL_MODEL) 2081 2082 assert readiness.artifacts["model_id"] == LOCAL_MODEL 2083 assert readiness.artifacts["model_path"] == str(gguf) 2084 assert readiness.artifacts["mmproj_path"] == str(mmproj) 2085 assert Path(readiness.artifacts["model_path"]).parent == local_install.model_dir( 2086 LOCAL_MODEL 2087 ) 2088 assert readiness.artifacts["model_path"] != str(stale_gguf) 2089 assert readiness.artifacts["model_installed"] is True 2090 2091 2092def test_inspect_readiness_not_installed_off_stale_record(tmp_path, monkeypatch): 2093 # With only the prior model's artifacts on disk and the selected model not 2094 # staged, readiness must report not-installed rather than claiming installed 2095 # off the stale record's gguf. 2096 _init_journal(tmp_path, monkeypatch) 2097 stale_dir = local_install.model_dir("local/old-coder-7b") 2098 stale_dir.mkdir(parents=True, exist_ok=True) 2099 stale_gguf = stale_dir / "coder-7b-Q4_K_M.gguf" 2100 stale_gguf.write_text("stale", encoding="utf-8") 2101 2102 readiness = local_install.inspect_readiness(LOCAL_MODEL) 2103 2104 assert readiness.artifacts["model_installed"] is False 2105 assert readiness.artifacts["gguf_installed"] is False 2106 assert readiness.artifacts["model_path"] == str( 2107 local_install.model_path(LOCAL_MODEL) 2108 ) 2109 2110 2111def test_install_llama_server_failure_writes_canonical_failed(tmp_path, monkeypatch): 2112 _init_journal(tmp_path, monkeypatch) 2113 pin = { 2114 "release_tag": "v1", 2115 "filename": "llama.tar.gz", 2116 "sha256": "abc123", 2117 "binary_name": "llama-server", 2118 } 2119 monkeypatch.setattr( 2120 local_install, "llama_server_artifact_key", lambda: "test-platform" 2121 ) 2122 monkeypatch.setattr(local_install, "pin_for_current_platform", lambda: pin) 2123 2124 def fake_download(_url, _dest, **_kwargs): 2125 raise RuntimeError("network broke") 2126 2127 monkeypatch.setattr(local_install, "_download_file", fake_download) 2128 2129 with pytest.raises(RuntimeError, match="network broke"): 2130 local_install.install_llama_server() 2131 2132 status = _local_status() 2133 assert status["install_state"] == "failed" 2134 assert status["install_error"] == "network broke"