Handy/src-tauri/src
Hoss a4999164ae
feat(models): add opt-in custom Whisper model discovery (#622)
* feat(models): auto-discover custom Whisper models in models directory

Enable automatic discovery of custom GGML-format Whisper models (.bin files)
placed in the models directory, so users don't need to modify source code
to use their own fine-tuned models.

Backend changes:
- Add discover_custom_whisper_models() to scan for .bin files
- Generate display names from filenames (e.g., "my-model" → "My Model")
- Skip predefined model filenames to avoid duplicates
- Add 3 unit tests for discovery logic

Frontend changes:
- Split model dropdown into 3 sections: Custom, Downloaded, Downloadable
- Add collapsible section for downloadable models to reduce clutter
- Add max-height with scroll for long model lists
- Add "Custom" badge for user-provided models

* feat(models): make custom Whisper model discovery opt-in

[why] Address maintainer concern about support burden from community
models. Custom models should be a power-user feature, not enabled by
default.

[how] Add custom_models_enabled setting (default: false) in Debug
settings. Discovery only runs when enabled. Models show "Not officially
supported" messaging. Documentation updated with enable steps.

* feat(models): add is_custom field and integrate custom models with new UI

[why]
PR review requested an explicit is_custom field instead of inferring
custom status from url === null. Custom models also need proper
integration with the new models settings page from PR #478.

[how]
- Add is_custom: bool to ModelInfo struct, set true on discovered models
- Change discover_custom_whisper_models signature from &PathBuf to &Path
- Use 0.0 sentinel scores so UI hides score bars for custom models
- Add "Custom Models" section to ModelsSettings with 3-way model split
- Show "Custom" badge in ModelCard and ModelDropdown
- Hide language/translation tags when supported_languages is empty
- Remove custom models from available_models on delete instead of
  just marking as not downloaded (they have no re-download URL)
- Update tests with new fields and assertions

* chore(i18n): add custom model translation keys to all locales

[why]
Custom model feature introduces 5 new translation keys that need
to be present in all 15 non-English locales for CI to pass.

[how]
Add English placeholder values for: customModelDescription,
modelSelector.custom, settings.models.customModels,
settings.debug.customModels.label, settings.debug.customModels.description

* fix(models): keep language filter visible when no models match

[why]
The language filter was inside a conditionally rendered section
that disappeared when no downloaded models matched the selected
language, leaving the user stuck with no way to change the filter.

[how]
Always render the "Your Models" header row with the language filter,
only conditionally render the model cards below it.

* docs: fix custom models section reference in README

Model selector → Models settings page.

* fix(models): apply custom models toggle immediately without restart

[why]
Two bugs reported in PR review: (1) app breaks on restart when a
custom model was selected and the toggle is disabled — selected_model
still points to the missing model, causing "Model not found" error.
(2) Custom models remain visible in the UI after toggle-off because
the in-memory model list is never updated and no event is emitted.

[how]
- Add remove_custom_models() and add_custom_models() to ModelManager
  for runtime mutation of the available_models mutex
- On disable: reset selected_model to empty if it's a custom model,
  then remove custom models from the in-memory list
- On enable: run discover_custom_whisper_models against the mutex
- Emit model-state-changed event so the frontend refreshes immediately

* chore(i18n): remove "restart required" from custom model descriptions

Toggle now takes effect immediately, so the restart sentence
is inaccurate. Updated all 16 locales and README instructions.

* fix(models): clear stale model selection on startup

[why]
If a custom model file is deleted from disk while it's the selected
model, the app gets stuck on "Loading..." forever on next launch
because the model ID is not in available_models but
auto_select_model_if_needed only checked for empty string.

[how]
Validate that selected_model exists in available_models before
accepting it. If not found, clear the selection so auto-select
picks a valid downloaded model.

* remove toggle and clean up

* format

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
2026-02-09 10:15:45 +08:00
..
audio_toolkit feat(text): Add n-gram matching for multi-word custom word correction (#711) 2026-02-05 18:29:25 +08:00
commands feat: add models settings page with filtering and management (#478) 2026-02-08 12:18:22 +08:00
helpers WIP: Add tauri-specta for generating TS bindings (#322) 2025-11-27 17:07:22 +07:00
managers feat(models): add opt-in custom Whisper model discovery (#622) 2026-02-09 10:15:45 +08:00
shortcut default for post-process and revert ui changes 2026-02-06 16:46:17 +08:00
actions.rs feat: add optional hotkey for post-processing request (#355) 2026-02-06 16:28:14 +08:00
apple_intelligence.rs Apple intel integration (#391) 2025-12-09 21:04:24 +07:00
audio_feedback.rs feat(audio): async play test sound (#375) 2025-11-27 17:46:41 +07:00
clipboard.rs feat(linux): add KDE Plasma 6 Wayland support via kwtype (#676) 2026-02-05 19:11:33 +08:00
input.rs refactor enigo input (#441) 2025-12-12 16:33:49 +07:00
lib.rs feat: add models settings page with filtering and management (#478) 2026-02-08 12:18:22 +08:00
llm_client.rs fix: replace async-openai library with post request (#480) 2025-12-27 11:21:27 +07:00
main.rs Set WEBKIT_DISABLE_DMABUF_RENDERER=1 in env (#427) 2025-12-11 13:01:04 +07:00
overlay.rs feat(overlay): add layer-shell for wayland support (#680) 2026-02-05 19:21:16 +08:00
settings.rs default for post-process and revert ui changes 2026-02-06 16:46:17 +08:00
signal_handle.rs Fix race condition when toggling transcription via SIGUSR2 (#560) 2026-01-10 11:38:58 +08:00
tray.rs feat(tray): add copy last transcript action (#598) 2026-01-18 10:33:50 +08:00
tray_i18n.rs feat: add tray menu localization using system locale (#446) 2025-12-18 04:14:32 -08:00
utils.rs feat(linux): add KDE Plasma 6 Wayland support via kwtype (#676) 2026-02-05 19:11:33 +08:00