Fixes the <unused49> regression that broke screenshot analysis and voice transcription. Adds a Model Hub for downloading and switching between model variants.
⚠️ Breaking: Model Source Change
ScreenMind now downloads models from ggml-org (official) instead of Unsloth, and stores them in ~/.screenmind/models/ instead of the HuggingFace cache. Existing users need to re-download their model from the new Model Hub.
See Discussion #14 for background on the mmproj incompatibility.
Migration: Clean up old cached models
The old Unsloth models in ~/.cache/huggingface/ are no longer used and can be safely deleted to free disk space (~3-5 GB):
# Windows
rmdir /s /q "%USERPROFILE%\.cache\huggingface\hub\models--unsloth--gemma-4-E2B-it-GGUF"
rmdir /s /q "%USERPROFILE%\.cache\huggingface\hub\models--unsloth--gemma-4-E4B-it-GGUF"
# macOS / Linux
rm -rf ~/.cache/huggingface/hub/models--unsloth--gemma-4-*✨ Features
-
Model Hub with variant selection — pick your preferred quantization (Q4_0, Q8_0, BF16, etc.) per model from the dashboard or settings. Download, switch, and delete variants independently. (model_manager.py, core.js, settings.js)
-
External server detection — if
llama-serveris already running on port 5809, ScreenMind adopts it instead of launching its own. Known models show as active; unknown models show an amber warning. (main.py) -
Voice memo resilience — memos are always saved to DB even if transcription fails or returns empty. Audio file is preserved for playback. (main.py)
-
Parallel analysis pipeline — embedding + developer context detection now run concurrently via
asyncio.gather(~2-3s faster per coding screenshot). (analysis_worker.py)
🐛 Bug Fixes
- Fix vision & audio producing
<unused49>garbage — switched from Unsloth to ggml-org models; their mmproj files stay compatible with llama.cpp updates <unusedN>token stripping — safety net regex filter inllm_client.pystrips garbage tokens from audio output- Fix: Voice recorder crash (SRDC) —
ScreenCapture(mss) uses Windows GDI handles that have thread affinity. The capture object was being created on the main thread but used from the hotkey listener thread, causing intermittent crashes when taking a screenshot during voice memo recording. Now creates a freshScreenCapture()per invocation with a try/except so a screenshot failure doesn't kill the voice memo. (voice_recorder.py) - Embedder API rename —
get_sentence_embedding_dimension()→get_embedding_dimension()for newer sentence-transformers (embedder.py)
📦 Models
| Model | Variants | VRAM |
|---|---|---|
| Gemma 4 E2B (2B) | Q4_0 · Q8_0 · BF16 | ~4 GB |
| Gemma 4 E4B (4B) | Q4_0 · Q8_0 · BF16 | ~6 GB |
| Gemma 4 12B | IQ3_M · Q4_K_M · Q5_K_M · Q6_K · Q8_0 | ~10 GB |
New users default to Gemma 4 E2B Q4_0 (~1.5 GB download).
🧪 Tests
test_model_manager.pyrewritten: 56 → 80 tests (variant lifecycle, external server detection)test_llm_client.py: +3 tests for token stripping- 473 tests passing
Upgrade
pip install --upgrade screenmindAfter upgrading, open Model Hub and download your preferred variant.
Full diff: v0.1.2...v0.2.0
PyPI: screenmind 0.2.0