personal memory agent
0
fork

Configure Feed

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

install_parakeet_model: verify FluidAudio-resolved cache path

_verify_mac_cache was checking the literal cache_dir, but FluidAudio's
downloadAndLoad(to:) writes into <parent>/<repo-folder-name> according to
its repoPath(from:) resolution.

For the pinned v3 CoreML model, the actual repo folder is
parakeet-tdt-0.6b-v3-coreml.

That made _verify_mac_cache always return False on Mac, so the install-time
sentinel was never written and repeated make install-models runs exited 1.

Resolve each expected model file under cache_dir.parent /
MAC_FLUIDAUDIO_REPO_NAME / <relpath> instead.

Also add three unit tests for the verifier: a positive case, a
sibling-empty negative case, and a literal-path negative case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+97 -1
+4 -1
scripts/install_parakeet_model.py
··· 23 23 PARAKEET_ONNX_VARIANT_ENV = "PARAKEET_ONNX_VARIANT" 24 24 HELPER_ENV_KEY = "SOLSTONE_PARAKEET_HELPER" 25 25 MAC_CACHE_DIR = Path.home() / "Library/Application Support/solstone/parakeet/models" 26 + # FluidAudio's downloadAndLoad(to:) treats the passed dir as the parent and writes into <parent>/<repo-folder>; this is the actual repo folder name pinned by FluidAudio v0.14.0 v3. 27 + MAC_FLUIDAUDIO_REPO_NAME = "parakeet-tdt-0.6b-v3-coreml" 26 28 MAC_SENTINEL = MAC_CACHE_DIR / ".install-complete" 27 29 LINUX_HUB_DIR = Path.home() / ".cache/huggingface/hub" 28 30 LINUX_MODEL_DIR = LINUX_HUB_DIR / "models--istupakov--parakeet-tdt-0.6b-v3-onnx" ··· 243 245 244 246 def _verify_mac_cache(cache_dir: Path) -> bool: 245 247 return all( 246 - (cache_dir / relative_path).is_file() for relative_path in MAC_MODEL_FILES 248 + (cache_dir.parent / MAC_FLUIDAUDIO_REPO_NAME / relative_path).is_file() 249 + for relative_path in MAC_MODEL_FILES 247 250 ) 248 251 249 252
+93
tests/test_install_parakeet_model.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 4 + from __future__ import annotations 5 + 6 + import json 7 + import subprocess 8 + import sys 9 + import tempfile 10 + from pathlib import Path 11 + 12 + ROOT = Path(__file__).resolve().parent.parent 13 + SCRIPT = ROOT / "scripts" / "install_parakeet_model.py" 14 + _PROBE = """ 15 + import json 16 + import runpy 17 + import sys 18 + from pathlib import Path 19 + 20 + ns = runpy.run_path(sys.argv[1]) 21 + action = sys.argv[2] 22 + 23 + if action == "constants": 24 + print( 25 + json.dumps( 26 + { 27 + "repo_name": ns["MAC_FLUIDAUDIO_REPO_NAME"], 28 + "model_files": ns["MAC_MODEL_FILES"], 29 + } 30 + ) 31 + ) 32 + elif action == "verify": 33 + print(json.dumps({"ok": ns["_verify_mac_cache"](Path(sys.argv[3]))})) 34 + else: 35 + raise AssertionError(f"unknown action: {action}") 36 + """ 37 + 38 + 39 + def _probe(action: str, cache_dir: Path | None = None) -> dict[str, object]: 40 + argv = [sys.executable, "-c", _PROBE, str(SCRIPT), action] 41 + if cache_dir is not None: 42 + argv.append(str(cache_dir)) 43 + result = subprocess.run(argv, check=True, capture_output=True, text=True) 44 + return json.loads(result.stdout) 45 + 46 + 47 + def _load_constants() -> tuple[str, tuple[str, ...]]: 48 + data = _probe("constants") 49 + return data["repo_name"], tuple(data["model_files"]) 50 + 51 + 52 + def _verify_mac_cache(cache_dir: Path) -> bool: 53 + data = _probe("verify", cache_dir) 54 + return bool(data["ok"]) 55 + 56 + 57 + def _write_model_files(base_dir: Path, relative_paths: tuple[str, ...]) -> None: 58 + for relative_path in relative_paths: 59 + target = base_dir / relative_path 60 + target.parent.mkdir(parents=True, exist_ok=True) 61 + target.write_bytes(b"ok") 62 + 63 + 64 + def test_verify_returns_true_when_files_at_fluidaudio_sibling(): 65 + with tempfile.TemporaryDirectory() as tmp_dir: 66 + repo_name, model_files = _load_constants() 67 + tmp_path = Path(tmp_dir) 68 + cache_dir = tmp_path / "models" 69 + repo_dir = tmp_path / repo_name 70 + _write_model_files(repo_dir, model_files) 71 + 72 + assert _verify_mac_cache(cache_dir) is True 73 + 74 + 75 + def test_verify_returns_false_when_sibling_empty(): 76 + with tempfile.TemporaryDirectory() as tmp_dir: 77 + repo_name, _ = _load_constants() 78 + tmp_path = Path(tmp_dir) 79 + cache_dir = tmp_path / "models" 80 + cache_dir.mkdir() 81 + (tmp_path / repo_name).mkdir() 82 + 83 + assert _verify_mac_cache(cache_dir) is False 84 + 85 + 86 + def test_verify_returns_false_when_files_at_literal_path(): 87 + with tempfile.TemporaryDirectory() as tmp_dir: 88 + _, model_files = _load_constants() 89 + tmp_path = Path(tmp_dir) 90 + cache_dir = tmp_path / "models" 91 + _write_model_files(cache_dir, model_files) 92 + 93 + assert _verify_mac_cache(cache_dir) is False