feat(macos): local ASR model manager, menu-bar polish, and release 0.5.2

Adds a bundled local ASR model catalog for the macOS app with one-click
Sherpa Qwen3 / SenseVoice downloads (pause/resume, inline actions) and a
shared model storage directory used by MLX Qwen3. Fixes the light-mode
sidebar material and makes the menu-bar icon follow the system appearance
with a refreshed status mark. Renames the built product to OSGKeyboard.app.

Bumps version to 0.5.2 (build 19).
This commit is contained in:
Rocky
2026-07-09 08:55:37 +08:00
parent c2f07bd8d2
commit 200265fbd6
50 changed files with 4666 additions and 266 deletions
+36 -2
View File
@@ -107,8 +107,9 @@ final class MacDictationViewModel: ObservableObject {
/// Pre-load MLX weights + Metal shaders so the first dictation is fast.
func warmUpQwen3IfNeeded() {
guard config.engineMode == "local",
MacLocalASRPreferences.backend == .qwen3MLX,
MacLocalASRPreferences.qwen3ModelIsInstalled() else { return }
let model = MacLocalASRService.selectedModelDefinition(),
model.backend == .mlx,
MacLocalASRService.isModelInstalled(model) else { return }
let path = MacLocalASRPreferences.qwen3ModelPath
Task.detached(priority: .utility) {
_ = try? await MacQwen3ASREngine.shared.prepareIfNeeded(modelPath: path)
@@ -156,6 +157,39 @@ final class MacDictationViewModel: ObservableObject {
return "\(seconds)s"
}
var localModelReady: Bool {
_ = localModelRevision
if let model = MacLocalASRService.selectedModelDefinition() {
return MacLocalASRService.isModelInstalled(model)
}
return MacLocalASRPreferences.qwen3ModelIsInstalled()
}
/// Context-aware warning when local engine is selected but the active model is not ready.
var localModelWarningMessage: String? {
_ = localModelRevision
guard config.engineMode == "local" else { return nil }
if localModelReady { return nil }
guard let model = MacLocalASRService.selectedModelDefinition() else {
return MacL10n.string("mac.settings.localModelFallbackApple", language: config.uiLanguage)
}
if model.installKind == .manual {
return MacL10n.string("mac.settings.mlxModelMissing", language: config.uiLanguage)
}
return MacL10n.format(
"mac.settings.selectedModelMissing",
language: config.uiLanguage,
model.displayName
)
}
@Published private(set) var localModelRevision = 0
func bumpLocalModelRevision() {
localModelRevision += 1
objectWillChange.send()
}
var qwen3ModelInstalled: Bool {
MacLocalASRPreferences.qwen3ModelIsInstalled()
}