fix(A.2 #13): propagate whisper feature from kon crate through to kon-transcription

Review feedback: src-tauri/src/commands/models.rs was still naming
load_whisper unconditionally, so a --no-default-features workspace
build (kon-transcription without the whisper feature) would have
compiled the transcription crate cleanly but failed in the kon crate
as soon as it tried to resolve the load_whisper symbol.

Adds a matching [features] section to src-tauri/Cargo.toml:
- default = ["whisper"]
- whisper = ["kon-transcription/whisper"]

and declares the kon-transcription dep with default-features = false so
the feature actually propagates rather than being forced-on by the
child crate's default. Cfg-gates the load_whisper import in models.rs
and adds a companion match arm that returns a runtime error when the
feature is off, keeping the API shape intact.

Verified with both cargo build -p kon and cargo build -p kon
--no-default-features.
This commit is contained in:
2026-04-22 04:54:07 +01:00
parent f9b396a966
commit e4adcc1832
2 changed files with 19 additions and 2 deletions

View File

@@ -9,6 +9,15 @@ edition = "2021"
name = "kon_lib" name = "kon_lib"
crate-type = ["staticlib", "cdylib", "rlib"] crate-type = ["staticlib", "cdylib", "rlib"]
[features]
# Default build includes the Whisper backend. Disabling this feature
# also drops it from kon-transcription (see Cargo.toml in that crate)
# so a --no-default-features workspace build does not pull whisper-rs-sys.
# load_model_from_disk returns a runtime error for Engine::Whisper when
# this feature is off; Parakeet continues to work.
default = ["whisper"]
whisper = ["kon-transcription/whisper"]
[build-dependencies] [build-dependencies]
tauri-build = { version = "2", features = [] } tauri-build = { version = "2", features = [] }
# Used by the CSP regression guard in build.rs to parse tauri.conf.json # Used by the CSP regression guard in build.rs to parse tauri.conf.json
@@ -21,7 +30,7 @@ serde_json = "1"
# Workspace crates # Workspace crates
kon-core = { path = "../crates/core" } kon-core = { path = "../crates/core" }
kon-audio = { path = "../crates/audio" } kon-audio = { path = "../crates/audio" }
kon-transcription = { path = "../crates/transcription" } kon-transcription = { path = "../crates/transcription", default-features = false }
kon-ai-formatting = { path = "../crates/ai-formatting" } kon-ai-formatting = { path = "../crates/ai-formatting" }
kon-storage = { path = "../crates/storage" } kon-storage = { path = "../crates/storage" }
kon-cloud-providers = { path = "../crates/cloud-providers" } kon-cloud-providers = { path = "../crates/cloud-providers" }

View File

@@ -9,7 +9,9 @@ use kon_core::hardware::{self, CpuFeatures};
use kon_core::model_registry::{self, Engine, LanguageSupport, ModelEntry}; use kon_core::model_registry::{self, Engine, LanguageSupport, ModelEntry};
use kon_core::types::{AudioSamples, ModelId, TranscriptionOptions}; use kon_core::types::{AudioSamples, ModelId, TranscriptionOptions};
use kon_transcription::model_manager; use kon_transcription::model_manager;
use kon_transcription::{load_parakeet, load_whisper, LocalEngine, Transcriber}; use kon_transcription::{load_parakeet, LocalEngine, Transcriber};
#[cfg(feature = "whisper")]
use kon_transcription::load_whisper;
/// Map legacy size strings to ModelId. /// Map legacy size strings to ModelId.
fn whisper_model_id(size: &str) -> ModelId { fn whisper_model_id(size: &str) -> ModelId {
@@ -78,6 +80,7 @@ pub fn load_model_from_disk(
model_registry::find_model(model_id).ok_or_else(|| format!("Unknown model: {model_id}"))?; model_registry::find_model(model_id).ok_or_else(|| format!("Unknown model: {model_id}"))?;
match entry.engine { match entry.engine {
#[cfg(feature = "whisper")]
Engine::Whisper => { Engine::Whisper => {
let dir = model_manager::model_dir(model_id); let dir = model_manager::model_dir(model_id);
let model_file = entry let model_file = entry
@@ -90,6 +93,11 @@ pub fn load_model_from_disk(
} }
load_whisper(&model_file).map_err(|e| e.to_string()) load_whisper(&model_file).map_err(|e| e.to_string())
} }
#[cfg(not(feature = "whisper"))]
Engine::Whisper => Err(format!(
"Whisper backend not compiled in this build (kon built without the \"whisper\" feature); \
cannot load {model_id}"
)),
Engine::Parakeet => { Engine::Parakeet => {
let dir = model_manager::model_dir(model_id); let dir = model_manager::model_dir(model_id);
if !dir.exists() { if !dir.exists() {