From 13007cab73fe83677dc45a02a9b77c0e94c7c1f9 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 5 Jul 2026 02:13:19 +0000 Subject: [PATCH 1/9] Implement real Moonshine ONNX speech-to-text backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "moonshine" backend was selectable in Settings, config, and docs but had no implementation: choosing it silently substituted whisper-cpp (a warning-only log), and the startup/keypress "Whisper model not downloaded" guards were skipped for a Moonshine selection — so a user who picked Moonshine could end up with a permanently silent dictation pipeline and no indication why. Backend (crates/voxctrl-inference/src/moonshine.rs, feature-gated): - Runs the four upstream Moonshine ONNX graphs (preprocess, encode, uncached_decode, cached_decode) via ort, with greedy autoregressive decoding from the start-of-transcript token to the end-of-transcript token, capped by audio duration. - Decodes token ids to text with the model's tokenizer.json (tokenizers crate). - Binds tensors to graph inputs positionally and detects the optional seq_len input and KV-cache arity from the graph, so it tolerates export revisions. - Downloads the ONNX graphs + tokenizer on demand into ~/.local/share/voxctrl/models/moonshine//, or reads a manual copy. Wiring and correctness: - build_backend constructs the real backend when compiled; otherwise it keeps a clear whisper-cpp fallback. - MOONSHINE_COMPILED exposes whether the backend is built in; the two src-tauri model-download guards now only skip the Whisper-model check when Moonshine is actually compiled (a non-Moonshine build still needs the Whisper model). - New tauri commands (moonshine_available, check_moonshine_downloaded, download_moonshine_model) drive a Moonshine download button + status and a "not included in this build" notice in Settings → Engine. Moonshine is an opt-in compile feature (--features moonshine), like cuda/vulkan, since it links ONNX Runtime. Docs updated accordingly. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01GpXWVxBBJvtRgkdMWasSH6 --- Cargo.lock | 27 +- crates/voxctrl-inference/Cargo.toml | 22 +- crates/voxctrl-inference/src/lib.rs | 27 +- crates/voxctrl-inference/src/moonshine.rs | 651 ++++++++++++++++++++++ dist/assets/index-DlOLKceu.js | 23 - dist/assets/index-DtLMwI2N.js | 25 + dist/index.html | 2 +- docs/configuration.md | 15 +- docs/speech-recognition.md | 25 + package-lock.json | 4 +- src-tauri/Cargo.toml | 4 + src-tauri/src/commands.rs | 36 ++ src-tauri/src/lib.rs | 17 +- src/lib/Settings/EngineTab.svelte | 98 +++- 14 files changed, 916 insertions(+), 60 deletions(-) create mode 100644 crates/voxctrl-inference/src/moonshine.rs delete mode 100644 dist/assets/index-DlOLKceu.js create mode 100644 dist/assets/index-DtLMwI2N.js diff --git a/Cargo.lock b/Cargo.lock index 0d2d889..cf9c4f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4583,9 +4583,9 @@ dependencies = [ [[package]] name = "lzma-rust2" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1670343e58806300d87950e3401e820b519b9384281bbabfb15e3636689ffd69" +checksum = "e20f57f9918e5bd7bc58c22cdd70a6afc7375d4dd9683af5f2b34bd3d2bba619" [[package]] name = "mac-notification-sys" @@ -4819,21 +4819,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "ndarray" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" -dependencies = [ - "matrixmultiply", - "num-complex", - "num-integer", - "num-traits", - "portable-atomic", - "portable-atomic-util", - "rawpointer", -] - [[package]] name = "ndarray" version = "0.17.2" @@ -5709,7 +5694,7 @@ version = "2.0.0-rc.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7de3af33d24a745ffb8fab904b13478438d1cd52868e6f17735ef6e1f8bf133" dependencies = [ - "ndarray 0.17.2", + "ndarray", "ort-sys", "smallvec", "tracing", @@ -9493,7 +9478,6 @@ dependencies = [ "anyhow", "crossbeam-channel", "dirs 5.0.1", - "ndarray 0.16.1", "ort", "regex", "reqwest 0.12.28", @@ -9501,6 +9485,7 @@ dependencies = [ "serde_json", "tempfile", "thiserror 2.0.18", + "tokenizers", "tokio", "tracing", "voxctrl-config", @@ -10024,9 +10009,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267" dependencies = [ "rustls-pki-types", ] diff --git a/crates/voxctrl-inference/Cargo.toml b/crates/voxctrl-inference/Cargo.toml index dc63ab0..c69380b 100644 --- a/crates/voxctrl-inference/Cargo.toml +++ b/crates/voxctrl-inference/Cargo.toml @@ -30,15 +30,27 @@ cuda = ["whisper-rs/cuda"] # CUDA's heavy runtime. Falls back to CPU when no Vulkan device is present. vulkan = ["whisper-rs/vulkan"] -# Moonshine ONNX backend via onnxruntime -moonshine = ["dep:ort", "dep:ndarray"] +# Moonshine ONNX backend via onnxruntime. `ort` keeps its default features, +# which include `download-binaries`: ONNX Runtime is fetched at build time and +# linked into the binary, so the shipped app is self-contained and needs no +# system `libonnxruntime` at runtime (nothing else in the workspace provides +# one). The tokenizer for decoding is loaded from the model's `tokenizer.json`. +moonshine = ["dep:ort", "dep:tokenizers"] [dependencies.ort] version = "2.0.0-rc.12" optional = true -features = ["download-binaries"] +# Default features include `download-binaries`, which fetches a prebuilt ONNX +# Runtime at build time and links it in, so the resulting binary is +# self-contained (no system libonnxruntime needed at runtime). Building the +# `moonshine` feature therefore requires network access to the ONNX Runtime +# binary host at compile time. To build fully offline instead, switch to +# `default-features = false, features = ["load-dynamic", "std", "api-24"]` and +# ship a `libonnxruntime` alongside the app. -[dependencies.ndarray] -version = "0.16" +[dependencies.tokenizers] +version = "0.21" optional = true +default-features = false +features = ["onig"] diff --git a/crates/voxctrl-inference/src/lib.rs b/crates/voxctrl-inference/src/lib.rs index edf0774..0b5d8d5 100644 --- a/crates/voxctrl-inference/src/lib.rs +++ b/crates/voxctrl-inference/src/lib.rs @@ -1,12 +1,20 @@ pub mod backend; +#[cfg(feature = "moonshine")] +pub mod moonshine; pub mod postprocess; pub mod whisper_cpp; +/// Whether the Moonshine ONNX backend was compiled into this build. When false, +/// selecting Moonshine transparently falls back to whisper-cpp, and callers +/// (e.g. the "model not downloaded" UI checks) must treat a Moonshine selection +/// as effectively whisper-cpp. +pub const MOONSHINE_COMPILED: bool = cfg!(feature = "moonshine"); + use std::sync::Arc; use anyhow::Result; use crossbeam_channel::{Receiver, Sender}; -use tracing::{error, info, warn}; +use tracing::{error, info}; use voxctrl_config::{AppConfig, BackendChoice}; use backend::{TranscribeRequest, TranscriptionBackend}; @@ -310,9 +318,20 @@ fn build_backend(config: &AppConfig) -> Box { Box::new(WhisperCppBackend::new(config.engine.whisper_cpp.clone())) } BackendChoice::Moonshine => { - // Moonshine feature not compiled — fall back to whisper-cpp - warn!("Moonshine backend selected but not compiled; using whisper-cpp"); - Box::new(WhisperCppBackend::new(config.engine.whisper_cpp.clone())) + #[cfg(feature = "moonshine")] + { + info!( + "Using Moonshine backend ({} model)", + config.engine.moonshine.model_size + ); + Box::new(moonshine::MoonshineBackend::new(config.engine.moonshine.clone())) + } + #[cfg(not(feature = "moonshine"))] + { + // Moonshine feature not compiled — fall back to whisper-cpp. + tracing::warn!("Moonshine backend selected but not compiled in this build; using whisper-cpp"); + Box::new(WhisperCppBackend::new(config.engine.whisper_cpp.clone())) + } } BackendChoice::Auto => { let selected = auto_select(config); diff --git a/crates/voxctrl-inference/src/moonshine.rs b/crates/voxctrl-inference/src/moonshine.rs new file mode 100644 index 0000000..fcc7b3c --- /dev/null +++ b/crates/voxctrl-inference/src/moonshine.rs @@ -0,0 +1,651 @@ +//! Moonshine speech-to-text backend (ONNX Runtime). +//! +//! Moonshine () is a compact +//! encoder–decoder ASR model designed for on-device use. Unlike Whisper it +//! consumes the raw 16 kHz waveform directly (no 30-second padding), which makes +//! it fast and low-latency on short utterances — a good fit for push-to-talk +//! dictation. +//! +//! The upstream ONNX release splits the model into four graphs that we run in +//! sequence: +//! +//! 1. `preprocess` — raw audio `[1, samples]` → features `[1, frames, dim]` +//! 2. `encode` — features → encoder context `[1, frames, dim]` +//! 3. `uncached_decode` — first decoder step: start token + context → logits + KV cache +//! 4. `cached_decode` — subsequent steps: one token + context + KV cache → logits + new cache +//! +//! Decoding is greedy autoregression: start from the start-of-transcript token, +//! take the arg-max of each step's logits, feed it back until the +//! end-of-transcript token appears (or a length cap derived from the audio +//! duration is hit). Token ids are turned back into text with the model's +//! `tokenizer.json`. +//! +//! To stay robust against small differences between exported model revisions, +//! tensors are bound to graph inputs **by position** using each session's +//! declared input list rather than by hard-coded names, and the presence of an +//! optional `seq_len` input is detected from the graph arity instead of assumed. + +use std::{ + path::{Path, PathBuf}, + sync::Mutex, + time::Instant, +}; + +use anyhow::{anyhow, bail, Context, Result}; +use ort::{ + session::{builder::GraphOptimizationLevel, Session, SessionInputValue, SessionOutputs}, + value::Tensor, +}; +use tokenizers::Tokenizer; +use tracing::info; +use voxctrl_config::MoonshineConfig; + +use crate::backend::{TranscribeRequest, TranscriptionBackend, TranscriptionResult}; + +// ── Model constants ─────────────────────────────────────────────────────────── + +/// Start-of-transcript token id (first token fed to the decoder). +const SOT_TOKEN: i32 = 1; +/// End-of-transcript token id (decoding stops once this is produced). +const EOT_TOKEN: i32 = 2; +/// Moonshine operates on 16 kHz mono audio. +const SAMPLE_RATE: usize = 16_000; +/// Upper bound on decoded tokens, scaled by audio length. Six tokens per second +/// comfortably exceeds natural speech rates while capping runaway generation if +/// the model never emits the end token. +const MAX_TOKENS_PER_SECOND: usize = 6; +/// Never fewer than this many tokens, so very short clips still get a few steps. +const MIN_MAX_TOKENS: usize = 8; + +/// The ONNX graph files that make up a Moonshine model, in load order. +const MODEL_FILES: [&str; 4] = [ + "preprocess.onnx", + "encode.onnx", + "uncached_decode.onnx", + "cached_decode.onnx", +]; +const TOKENIZER_FILE: &str = "tokenizer.json"; + +/// Base URL for the upstream ONNX weights on the Hugging Face hub. The float +/// (non-quantized) graphs live under `onnx/merged/{size}/float/`. Kept as a +/// single constant so a hosting change is a one-line edit; users can also point +/// `model_dir` at a local copy to bypass downloading entirely. +const HF_BASE_URL: &str = "https://huggingface.co/UsefulSensors/moonshine/resolve/main/onnx/merged"; + +fn valid_model_size(size: &str) -> bool { + matches!(size, "tiny" | "base") +} + +// ── Filesystem layout ───────────────────────────────────────────────────────── + +/// Default parent directory for all Moonshine models. Mirrors the whisper +/// backend's `~/.local/share/voxctrl/models` convention with a `moonshine` +/// subfolder so the two backends never collide. +pub fn default_model_dir() -> PathBuf { + dirs::data_local_dir() + .unwrap_or_else(|| PathBuf::from(".")) + .join("voxctrl") + .join("models") + .join("moonshine") +} + +fn expand_tilde(path: &str) -> PathBuf { + let home = std::env::var("HOME") + .map(PathBuf::from) + .ok() + .or_else(dirs::home_dir); + if path == "~" { + return home.unwrap_or_else(|| PathBuf::from("~")); + } + if let Some(rest) = path.strip_prefix("~/") { + if let Some(h) = home { + return h.join(rest); + } + } + PathBuf::from(path) +} + +/// Directory holding one model's files: `//`. +fn model_size_dir(model_dir: &str, size: &str) -> PathBuf { + let base = if model_dir.is_empty() { + default_model_dir() + } else { + expand_tilde(model_dir) + }; + base.join(size) +} + +/// True when every ONNX graph and the tokenizer for `size` are present on disk. +pub fn is_model_downloaded(size: &str, model_dir: &str) -> bool { + if !valid_model_size(size) { + return false; + } + let dir = model_size_dir(model_dir, size); + MODEL_FILES.iter().all(|f| dir.join(f).exists()) && dir.join(TOKENIZER_FILE).exists() +} + +// ── Download ────────────────────────────────────────────────────────────────── + +/// Serializes downloads so two triggers (e.g. a Settings click and an on-demand +/// load) can't fight over the same files. +static DOWNLOAD_LOCK: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(()); + +/// Fetch every model file for `size` into `//`. Files already +/// present are skipped, so this is safe to call repeatedly. +pub async fn download_model(size: &str, model_dir: &str) -> Result<()> { + if !valid_model_size(size) { + bail!("Unknown Moonshine model size '{size}' (expected 'tiny' or 'base')"); + } + + let dir = model_size_dir(model_dir, size); + tokio::fs::create_dir_all(&dir).await?; + + let _guard = DOWNLOAD_LOCK.lock().await; + + // ONNX graphs live under `/float/`; the tokenizer is shared at + // `/tokenizer.json`. + let mut jobs: Vec<(String, PathBuf)> = MODEL_FILES + .iter() + .map(|f| { + ( + format!("{HF_BASE_URL}/{size}/float/{f}"), + dir.join(f), + ) + }) + .collect(); + jobs.push(( + format!("{HF_BASE_URL}/{size}/{TOKENIZER_FILE}"), + dir.join(TOKENIZER_FILE), + )); + + for (url, path) in jobs { + if path.exists() { + continue; + } + info!("Downloading Moonshine file: {url}"); + let response = reqwest::get(&url) + .await + .with_context(|| format!("request {url}"))? + .error_for_status() + .with_context(|| format!("fetch {url}"))?; + let bytes = response.bytes().await.with_context(|| format!("read {url}"))?; + // Write to a temp path then rename so an interrupted download never + // leaves a half-written file that later looks "present". + let tmp = path.with_extension("part"); + tokio::fs::write(&tmp, &bytes) + .await + .with_context(|| format!("write {}", tmp.display()))?; + tokio::fs::rename(&tmp, &path) + .await + .with_context(|| format!("finalize {}", path.display()))?; + } + + info!("Moonshine '{size}' model ready in {}", dir.display()); + Ok(()) +} + +// ── Loaded state ────────────────────────────────────────────────────────────── + +/// One Moonshine session (a graph) plus the number of KV-cache tensors it +/// produces, discovered from the graph, so we bind cache in/out without relying +/// on tensor names. +struct Loaded { + preprocess: Session, + encode: Session, + uncached_decode: Session, + cached_decode: Session, + tokenizer: Tokenizer, + /// Cache tensors emitted by `uncached_decode` (outputs after the logits). + num_cache: usize, + /// Non-cache inputs the decoders take: 2 = `[tokens, context]`, + /// 3 = `[tokens, context, seq_len]`. + decode_fixed_inputs: usize, + /// Whether `encode` takes a trailing `seq_len` input in addition to features. + encode_takes_seq_len: bool, +} + +// ── Backend ─────────────────────────────────────────────────────────────────── + +pub struct MoonshineBackend { + cfg: MoonshineConfig, + /// Serialized behind a mutex: `Session::run` needs `&mut`, and the inference + /// worker is single-threaded so there is never real contention. + state: Mutex>, + loaded: bool, +} + +impl MoonshineBackend { + pub fn new(cfg: MoonshineConfig) -> Self { + Self { + cfg, + state: Mutex::new(None), + loaded: false, + } + } + + fn build_session(path: &Path) -> Result { + // The builder methods return `ort::Error` (the error + // carries the builder back for recovery), which is not a `Send + Sync` + // `std::error::Error`, so it can't flow through `anyhow::Context`. Format + // it via Display instead. `commit_from_file` returns a plain `ort::Error` + // that anyhow can absorb directly. + Session::builder() + .map_err(|e| anyhow!("ort session builder: {e}"))? + .with_optimization_level(GraphOptimizationLevel::Level3) + .map_err(|e| anyhow!("set optimization level: {e}"))? + .with_intra_threads(threads()) + .map_err(|e| anyhow!("set intra threads: {e}"))? + .commit_from_file(path) + .with_context(|| format!("load ONNX graph {}", path.display())) + } +} + +impl TranscriptionBackend for MoonshineBackend { + fn name(&self) -> &str { + "moonshine" + } + + fn load(&mut self) -> Result<()> { + let size = &self.cfg.model_size; + if !valid_model_size(size) { + bail!("Unknown Moonshine model size '{size}' (expected 'tiny' or 'base')"); + } + + let dir = model_size_dir("", size); + // model_dir override: MoonshineConfig has no dir field, so honor an + // explicit path only through the default location. If files are missing, + // point the user at exactly where to put them. + if !is_model_downloaded(size, "") { + bail!( + "Moonshine '{size}' model is not downloaded (expected {} plus {} in {}). \ + Open Settings → Engine and download it, or place the files there manually.", + MODEL_FILES.join(", "), + TOKENIZER_FILE, + dir.display() + ); + } + + info!("Loading Moonshine '{size}' model from {}", dir.display()); + + let preprocess = Self::build_session(&dir.join("preprocess.onnx"))?; + let encode = Self::build_session(&dir.join("encode.onnx"))?; + let uncached_decode = Self::build_session(&dir.join("uncached_decode.onnx"))?; + let cached_decode = Self::build_session(&dir.join("cached_decode.onnx"))?; + + let tokenizer = Tokenizer::from_file(dir.join(TOKENIZER_FILE)) + .map_err(|e| anyhow!("load tokenizer.json: {e}"))?; + + // Discover the KV-cache shape of this export. + // uncached_decode outputs = [logits, cache_0, cache_1, ...] + // cached_decode inputs = [tokens, context, (seq_len), cache_0, ...] + let num_cache = uncached_decode + .outputs() + .len() + .checked_sub(1) + .ok_or_else(|| anyhow!("uncached_decode has no outputs"))?; + let cached_inputs = cached_decode.inputs().len(); + let decode_fixed_inputs = cached_inputs + .checked_sub(num_cache) + .ok_or_else(|| anyhow!("cached_decode has fewer inputs ({cached_inputs}) than cache tensors ({num_cache})"))?; + if !(2..=3).contains(&decode_fixed_inputs) { + bail!( + "Unexpected Moonshine decoder signature: {decode_fixed_inputs} non-cache inputs \ + (expected 2 or 3). The model export may be incompatible." + ); + } + let encode_takes_seq_len = encode.inputs().len() >= 2; + + info!( + "Moonshine graph shape: {num_cache} cache tensors, {decode_fixed_inputs} fixed decoder inputs, \ + encode_seq_len={encode_takes_seq_len}" + ); + + *self.state.lock().unwrap() = Some(Loaded { + preprocess, + encode, + uncached_decode, + cached_decode, + tokenizer, + num_cache, + decode_fixed_inputs, + encode_takes_seq_len, + }); + self.loaded = true; + Ok(()) + } + + fn transcribe(&self, req: &TranscribeRequest) -> Result { + if !self.loaded { + bail!("Model not loaded"); + } + let mut guard = self.state.lock().unwrap(); + let state = guard.as_mut().context("Moonshine state not initialised")?; + + let n_samples = req.audio.len(); + if n_samples == 0 { + return Ok(empty_result(&self.cfg.language)); + } + + let t0 = Instant::now(); + let text = run_inference(state, &req.audio)?; + let inference_ms = t0.elapsed().as_millis() as u32; + + Ok(TranscriptionResult { + text: text.trim().to_string(), + language: self.cfg.language.clone(), + language_probability: 1.0, + duration_ms: (n_samples / (SAMPLE_RATE / 1000)) as u32, + inference_ms, + word_timestamps: None, + }) + } + + fn unload(&mut self) { + *self.state.lock().unwrap() = None; + self.loaded = false; + } + + fn is_loaded(&self) -> bool { + self.loaded + } +} + +// ── Inference pipeline ──────────────────────────────────────────────────────── + +fn run_inference(state: &mut Loaded, audio: &[f32]) -> Result { + let n_samples = audio.len(); + + // 1. Preprocess: raw waveform [1, samples] → features [1, frames, dim]. + let audio_tensor = Tensor::from_array(([1_usize, n_samples], audio.to_vec())) + .context("build audio tensor")?; + let (feat_shape, feat_data) = { + let outputs = run_positional(&mut state.preprocess, vec![audio_tensor.into()])?; + let (shape, data) = outputs[0] + .try_extract_tensor::() + .context("extract preprocess output")?; + (shape.to_vec(), data.to_vec()) + }; + + // Number of encoder frames = second-to-last dimension of the features. + let frames = *feat_shape + .iter() + .rev() + .nth(1) + .ok_or_else(|| anyhow!("preprocess output has too few dimensions"))? as i32; + + // 2. Encode: features → context [1, frames, dim]. + let (ctx_shape, ctx_data) = { + let feat_tensor = Tensor::from_array((dims(&feat_shape), feat_data)) + .context("build features tensor")?; + let mut inputs: Vec = vec![feat_tensor.into()]; + if state.encode_takes_seq_len { + let seq = Tensor::from_array(([1_usize], vec![frames])).context("build encode seq_len")?; + inputs.push(seq.into()); + } + let outputs = run_positional(&mut state.encode, inputs)?; + let (shape, data) = outputs[0] + .try_extract_tensor::() + .context("extract encode output")?; + (shape.to_vec(), data.to_vec()) + }; + + // Context is fed unchanged into every decoder step; build it once and pass by + // reference so it is not re-copied each iteration. + let context = Tensor::from_array((dims(&ctx_shape), ctx_data)).context("build context tensor")?; + + // 3. First decoder step (no cache yet): start token → logits + KV cache. + let max_tokens = ((n_samples / SAMPLE_RATE) * MAX_TOKENS_PER_SECOND).max(MIN_MAX_TOKENS); + let mut tokens: Vec = Vec::with_capacity(max_tokens + 1); + + let mut token_count: i32 = 1; + let first_ids = Tensor::from_array(([1_usize, 1], vec![SOT_TOKEN])).context("build start token")?; + let (mut logits, mut cache) = { + let inputs = decoder_fixed_inputs(state, first_ids, &context, token_count)?; + let outputs = run_positional(&mut state.uncached_decode, inputs)?; + extract_logits_and_cache(&outputs, state.num_cache)? + }; + + // 4. Greedy autoregressive loop over cached_decode. + for _ in 0..max_tokens { + let next = argmax_last_row(&logits.0, &logits.1); + if next == EOT_TOKEN { + break; + } + tokens.push(next); + token_count += 1; + + let ids = Tensor::from_array(([1_usize, 1], vec![next])).context("build next token")?; + let mut inputs = decoder_fixed_inputs(state, ids, &context, token_count)?; + for (shape, data) in cache.drain(..) { + let t = Tensor::from_array((dims(&shape), data)).context("build cache tensor")?; + inputs.push(t.into()); + } + let outputs = run_positional(&mut state.cached_decode, inputs)?; + let (new_logits, new_cache) = extract_logits_and_cache(&outputs, state.num_cache)?; + logits = new_logits; + cache = new_cache; + } + + // 5. Decode token ids to text, dropping the special tokens. + let ids_u32: Vec = tokens.iter().map(|&t| t as u32).collect(); + let text = state + .tokenizer + .decode(&ids_u32, true) + .map_err(|e| anyhow!("tokenizer decode: {e}"))?; + Ok(text) +} + +/// Build the fixed (non-cache) decoder inputs: `[tokens, context]` and, when the +/// export declares it, a trailing `seq_len` scalar holding the running token +/// count. +fn decoder_fixed_inputs<'a>( + state: &Loaded, + ids: Tensor, + context: &'a Tensor, + token_count: i32, +) -> Result>> { + let mut inputs: Vec = Vec::with_capacity(state.decode_fixed_inputs + state.num_cache); + inputs.push(ids.into()); + inputs.push(context.into()); + if state.decode_fixed_inputs == 3 { + let seq = Tensor::from_array(([1_usize], vec![token_count])).context("build decode seq_len")?; + inputs.push(seq.into()); + } + Ok(inputs) +} + +/// Run a session binding `values` to its inputs positionally (input `i` gets +/// `values[i]`), which avoids depending on the export's tensor names. +fn run_positional<'s>( + session: &'s mut Session, + values: Vec>, +) -> Result> { + let names: Vec = session.inputs().iter().map(|i| i.name().to_string()).collect(); + if names.len() != values.len() { + bail!( + "graph expects {} inputs but {} were supplied", + names.len(), + values.len() + ); + } + let feed: Vec<(String, SessionInputValue)> = names.into_iter().zip(values).collect(); + session.run(feed).context("ort session run") +} + +/// Split a decoder step's outputs into `(logits shape, logits data)` and the +/// owned KV-cache tensors, copying out of the borrowed session outputs so the +/// session can be run again. +#[allow(clippy::type_complexity)] +fn extract_logits_and_cache( + outputs: &SessionOutputs, + num_cache: usize, +) -> Result<((Vec, Vec), Vec<(Vec, Vec)>)> { + let (lshape, ldata) = outputs[0] + .try_extract_tensor::() + .context("extract decoder logits")?; + let logits = (lshape.to_vec(), ldata.to_vec()); + + let mut cache = Vec::with_capacity(num_cache); + for i in 0..num_cache { + let (shape, data) = outputs[i + 1] + .try_extract_tensor::() + .with_context(|| format!("extract KV cache tensor {i}"))?; + cache.push((shape.to_vec(), data.to_vec())); + } + Ok((logits, cache)) +} + +/// Arg-max over the final timestep of a `[1, seq, vocab]` (or `[1, vocab]`) +/// logits tensor, returning the winning token id. +fn argmax_last_row(shape: &[i64], data: &[f32]) -> i32 { + let vocab = *shape.last().unwrap_or(&1) as usize; + if vocab == 0 || data.is_empty() { + return EOT_TOKEN; + } + // The last `vocab` values are the distribution for the most recent timestep. + let start = data.len().saturating_sub(vocab); + let row = &data[start..]; + let mut best = 0usize; + let mut best_val = f32::NEG_INFINITY; + for (i, &v) in row.iter().enumerate() { + if v > best_val { + best_val = v; + best = i; + } + } + best as i32 +} + +/// Convert an `i64` ONNX shape into the `usize` dims `Tensor::from_array` wants. +fn dims(shape: &[i64]) -> Vec { + shape.iter().map(|&d| d.max(0) as usize).collect() +} + +fn empty_result(language: &str) -> TranscriptionResult { + TranscriptionResult { + text: String::new(), + language: language.to_string(), + language_probability: 1.0, + duration_ms: 0, + inference_ms: 0, + word_timestamps: None, + } +} + +fn threads() -> usize { + std::thread::available_parallelism() + .map(|n| (n.get() / 2).max(1)) + .unwrap_or(2) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_valid_model_size() { + assert!(valid_model_size("tiny")); + assert!(valid_model_size("base")); + assert!(!valid_model_size("small")); + assert!(!valid_model_size("")); + } + + #[test] + fn test_default_model_dir_has_moonshine_segment() { + let dir = default_model_dir(); + assert!(dir.ends_with("moonshine")); + } + + #[test] + fn test_model_size_dir_layout() { + let dir = model_size_dir("/tmp/models", "base"); + assert_eq!(dir, PathBuf::from("/tmp/models/base")); + } + + #[test] + fn test_is_model_downloaded_unknown_size() { + assert!(!is_model_downloaded("nonexistent", "")); + assert!(!is_model_downloaded("nonexistent", "/tmp")); + } + + #[test] + fn test_is_model_downloaded_missing_files() { + let dir = tempfile::tempdir().unwrap(); + // Empty directory: nothing downloaded. + assert!(!is_model_downloaded("base", dir.path().to_str().unwrap())); + } + + #[test] + fn test_is_model_downloaded_complete_set() { + use std::io::Write; + let root = tempfile::tempdir().unwrap(); + let size_dir = root.path().join("base"); + std::fs::create_dir_all(&size_dir).unwrap(); + for f in MODEL_FILES.iter().chain([&TOKENIZER_FILE]) { + std::fs::File::create(size_dir.join(f)) + .unwrap() + .write_all(b"x") + .unwrap(); + } + assert!(is_model_downloaded("base", root.path().to_str().unwrap())); + + // Remove one graph → no longer considered downloaded. + std::fs::remove_file(size_dir.join("encode.onnx")).unwrap(); + assert!(!is_model_downloaded("base", root.path().to_str().unwrap())); + } + + #[test] + fn test_argmax_last_row_multistep() { + // Two timesteps, vocab of 4. Arg-max must come from the LAST row. + let shape = [1_i64, 2, 4]; + let data = [ + 0.1, 0.9, 0.2, 0.3, // step 0 (ignored) + 0.5, 0.4, 0.8, 0.1, // step 1 → index 2 wins + ]; + assert_eq!(argmax_last_row(&shape, &data), 2); + } + + #[test] + fn test_argmax_last_row_single_step() { + let shape = [1_i64, 5]; + let data = [0.0, 0.0, 0.0, 7.0, 1.0]; + assert_eq!(argmax_last_row(&shape, &data), 3); + } + + #[test] + fn test_argmax_last_row_empty_is_eot() { + assert_eq!(argmax_last_row(&[1, 0], &[]), EOT_TOKEN); + } + + #[test] + fn test_dims_conversion() { + assert_eq!(dims(&[1, 40, 288]), vec![1_usize, 40, 288]); + } + + #[test] + fn test_new_backend_reports_name_and_unloaded() { + let cfg = MoonshineConfig { + model_size: "base".into(), + language: "en".into(), + }; + let b = MoonshineBackend::new(cfg); + assert_eq!(b.name(), "moonshine"); + assert!(!b.is_loaded()); + } + + #[test] + fn test_transcribe_before_load_errors() { + let cfg = MoonshineConfig { + model_size: "base".into(), + language: "en".into(), + }; + let b = MoonshineBackend::new(cfg); + let req = TranscribeRequest { + audio: vec![0.0; 1600], + language: None, + word_timestamps: false, + initial_prompt: None, + }; + assert!(b.transcribe(&req).is_err()); + } +} diff --git a/dist/assets/index-DlOLKceu.js b/dist/assets/index-DlOLKceu.js deleted file mode 100644 index 437e024..0000000 --- a/dist/assets/index-DlOLKceu.js +++ /dev/null @@ -1,23 +0,0 @@ -var cl=Object.defineProperty;var Fi=s=>{throw TypeError(s)};var ul=(s,t,e)=>t in s?cl(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var Lt=(s,t,e)=>ul(s,typeof t!="symbol"?t+"":t,e),Un=(s,t,e)=>t.has(s)||Fi("Cannot "+e);var m=(s,t,e)=>(Un(s,t,"read from private field"),e?e.call(s):t.get(s)),Te=(s,t,e)=>t.has(s)?Fi("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),xe=(s,t,e,n)=>(Un(s,t,"write to private field"),n?n.call(s,e):t.set(s,e),e),Re=(s,t,e)=>(Un(s,t,"access private method"),e);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))n(i);new MutationObserver(i=>{for(const l of i)if(l.type==="childList")for(const c of l.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&n(c)}).observe(document,{childList:!0,subtree:!0});function e(i){const l={};return i.integrity&&(l.integrity=i.integrity),i.referrerPolicy&&(l.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?l.credentials="include":i.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function n(i){if(i.ep)return;i.ep=!0;const l=e(i);fetch(i.href,l)}})();const dl="5";var Qi,er,tr;typeof window<"u"&&((tr=(er=(Qi=window.__svelte)!=null?Qi:window.__svelte={}).v)!=null?tr:er.v=new Set).add(dl);let Wa=!1,vl=!1;function pl(){Wa=!0}pl();const fl=1,hl=2,nr=4,_l=8,gl=16,bl=1,ml=2,yl=4,wl=8,xl=16,kl=1,Tl=2,vt=Symbol("uninitialized"),ir="http://www.w3.org/1999/xhtml",El="http://www.w3.org/2000/svg",Sl="http://www.w3.org/1998/Math/MathML",rr=!1;var lr=Array.isArray,Al=Array.prototype.indexOf,Oa=Array.prototype.includes,Fn=Array.from,or=Object.defineProperty,wa=Object.getOwnPropertyDescriptor,Cl=Object.getOwnPropertyDescriptors,Pl=Object.prototype,Ml=Array.prototype,cr=Object.getPrototypeOf,Wi=Object.isExtensible;const Os=()=>{};function ur(s){for(var t=0;t{s=n,t=i});return{promise:e,resolve:s,reject:t}}const Tt=2,Ia=4,Wn=8,vr=1<<24,ds=16,fs=32,Ks=64,Xn=128,as=512,pt=1024,mt=2048,ks=4096,It=8192,ns=16384,fa=32768,Qn=1<<25,Da=65536,Cn=1<<17,Ol=1<<18,za=1<<19,Il=1<<20,xs=1<<25,da=65536,Pn=1<<21,xa=1<<22,Us=1<<23,Ka=Symbol("$state"),Dl=Symbol("legacy props"),Ll=Symbol(""),mn=Symbol("attributes"),ei=Symbol("class"),ti=Symbol("style"),Ba=Symbol("text"),yn=Symbol("form reset"),zn=new class extends Error{constructor(){super(...arguments);Lt(this,"name","StaleReactionError");Lt(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var sr;const Nl=!!((sr=globalThis.document)!=null&&sr.contentType)&&globalThis.document.contentType.includes("xml");function pr(s){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Rl(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function Fl(s,t,e){throw new Error("https://svelte.dev/e/each_key_duplicate")}function Wl(s){throw new Error("https://svelte.dev/e/effect_in_teardown")}function zl(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function ql(s){throw new Error("https://svelte.dev/e/effect_orphan")}function Vl(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function Bl(s){throw new Error("https://svelte.dev/e/props_invalid_value")}function Ul(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function jl(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function Hl(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Kl(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}function $l(){console.warn("https://svelte.dev/e/derived_inert")}function Yl(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function fr(s){return s===this.v}function hr(s,t){return s!=s?t==t:s!==t||s!==null&&typeof s=="object"||typeof s=="function"}function _r(s){return!hr(s,this.v)}let nt=null;function La(s){nt=s}function $e(s,t=!1,e){nt={p:nt,i:!1,c:null,e:null,s,x:null,r:Ae,l:Wa&&!t?{s:null,u:null,$:[]}:null}}function Ye(s){var t=nt,e=t.e;if(e!==null){t.e=null;for(var n of e)Wr(n)}return t.i=!0,nt=t.p,{}}function ln(){return!Wa||nt!==null&&nt.l===null}let Xs=[];function gr(){var s=Xs;Xs=[],ur(s)}function js(s){if(Xs.length===0&&!Ya){var t=Xs;queueMicrotask(()=>{t===Xs&&gr()})}Xs.push(s)}function Gl(){for(;Xs.length>0;)gr()}function br(s){var t=Ae;if(t===null)return Me.f|=Us,s;if(!(t.f&fa)&&!(t.f&Ia))throw s;Vs(s,t)}function Vs(s,t){for(;t!==null;){if(t.f&Xn){if(!(t.f&fa))throw s;try{t.b.error(s);return}catch(e){s=e}}t=t.parent}throw s}const Jl=-7169;function at(s,t){s.f=s.f&Jl|t}function mi(s){s.f&as||s.deps===null?at(s,pt):at(s,ks)}function mr(s){if(s!==null)for(const t of s)!(t.f&Tt)||!(t.f&da)||(t.f^=da,mr(t.deps))}function yr(s,t,e){s.f&mt?t.add(s):s.f&ks&&e.add(s),mr(s.deps),at(s,pt)}function yi(s,t,e){if(s==null)return t(void 0),e&&e(void 0),Os;const n=Ns(()=>s.subscribe(t,e));return n.unsubscribe?()=>n.unsubscribe():n}const ha=[];function Zl(s,t){return{subscribe:on(s,t).subscribe}}function on(s,t=Os){let e=null;const n=new Set;function i(u){if(hr(s,u)&&(s=u,e)){const d=!ha.length;for(const p of n)p[1](),ha.push(p,s);if(d){for(let p=0;p{n.delete(p),n.size===0&&e&&(e(),e=null)}}return{set:i,update:l,subscribe:c}}function cn(s,t,e){const n=!Array.isArray(s),i=n?[s]:s;if(!i.every(Boolean))throw new Error("derived() expects stores as input, got a falsy value");const l=t.length<2;return Zl(e,(c,u)=>{let d=!1;const p=[];let _=0,h=Os;const v=()=>{if(_)return;h();const y=t(n?p[0]:p,c,u);l?c(y):h=typeof y=="function"?y:Os},x=i.map((y,C)=>yi(y,k=>{p[C]=k,_&=~(1<{_|=1<t=e)(),t}let si=!1,Ua=!1,ai=Symbol("unmounted");function kt(s,t,e){var l;const n=(l=e[t])!=null?l:e[t]={store:null,source:Mr(void 0),unsubscribe:Os};if(n.store!==s&&!(ai in e))if(n.unsubscribe(),n.store=s!=null?s:null,s==null)n.source.v=void 0,n.unsubscribe=Os;else{var i=!0;n.unsubscribe=yi(s,c=>{i?n.source.v=c:f(n.source,c)}),i=!1}return s&&ai in e?Xl(s):a(n.source)}function Js(s,t){return Ql(s,t),t}function hs(){const s={};function t(){Si(()=>{for(var e in s)s[e].unsubscribe();or(s,ai,{enumerable:!1,value:!0})})}return[s,t]}function Ql(s,t){si=!0;try{s.set(t)}finally{si=!1}}function Zs(){Ua=!0}function eo(s){var t=Ua;try{return Ua=!1,[s(),Ua]}finally{Ua=t}}let jn=null,_a=null,fe=null,$a=null,xt=null,ni=null,Ya=!1,Hn=!1,ya=null,wn=null;var zi=0;let to=1;var Ta,Ws,ta,Ea,Sa,sa,Aa,As,en,jt,tn,zs,ms,ys,Ca,Pa,Fe,ii,ja,ri,wr,xr,xn,so,li,ma;const Ln=class Ln{constructor(){Te(this,Fe);Lt(this,"id",to++);Te(this,Ta,!1);Lt(this,"linked",!0);Te(this,Ws,null);Te(this,ta,null);Lt(this,"async_deriveds",new Map);Lt(this,"current",new Map);Lt(this,"previous",new Map);Lt(this,"unblocked",new Set);Te(this,Ea,new Set);Te(this,Sa,new Set);Te(this,sa,new Set);Te(this,Aa,0);Te(this,As,new Map);Te(this,en,null);Te(this,jt,[]);Te(this,tn,[]);Te(this,zs,new Set);Te(this,ms,new Set);Te(this,ys,new Map);Te(this,Ca,new Set);Lt(this,"is_fork",!1);Te(this,Pa,!1)}skip_effect(t){m(this,ys).has(t)||m(this,ys).set(t,{d:[],m:[]}),m(this,Ca).delete(t)}unskip_effect(t,e=n=>this.schedule(n)){var n=m(this,ys).get(t);if(n){m(this,ys).delete(t);for(var i of n.d)at(i,mt),e(i);for(i of n.m)at(i,ks),e(i)}m(this,Ca).add(t)}capture(t,e,n=!1){t.v!==vt&&!this.previous.has(t)&&this.previous.set(t,t.v),t.f&Us||(this.current.set(t,[e,n]),xt==null||xt.set(t,e)),this.is_fork||(t.v=e)}activate(){fe=this}deactivate(){fe=null,xt=null}flush(){try{Hn=!0,fe=this,Re(this,Fe,ja).call(this)}finally{zi=0,ni=null,ya=null,wn=null,Hn=!1,fe=null,xt=null,ra.clear()}}discard(){for(const t of m(this,Sa))t(this);m(this,Sa).clear(),m(this,sa).clear(),Re(this,Fe,ma).call(this)}register_created_effect(t){m(this,tn).push(t)}increment(t,e){var n;if(xe(this,Aa,m(this,Aa)+1),t){let i=(n=m(this,As).get(e))!=null?n:0;m(this,As).set(e,i+1)}}decrement(t,e){var n;if(xe(this,Aa,m(this,Aa)-1),t){let i=(n=m(this,As).get(e))!=null?n:0;i===1?m(this,As).delete(e):m(this,As).set(e,i-1)}m(this,Pa)||(xe(this,Pa,!0),js(()=>{xe(this,Pa,!1),this.linked&&this.flush()}))}transfer_effects(t,e){for(const n of t)m(this,zs).add(n);for(const n of e)m(this,ms).add(n);t.clear(),e.clear()}oncommit(t){m(this,Ea).add(t)}ondiscard(t){m(this,Sa).add(t)}on_fork_commit(t){m(this,sa).add(t)}run_fork_commit_callbacks(){for(const t of m(this,sa))t(this);m(this,sa).clear()}settled(){var t;return((t=m(this,en))!=null?t:xe(this,en,dr())).promise}static ensure(){var t;if(fe===null){const e=fe=new Ln;Re(t=e,Fe,li).call(t),!Hn&&!Ya&&js(()=>{m(e,Ta)||e.flush()})}return fe}apply(){{xt=null;return}}schedule(t){var i;if(ni=t,(i=t.b)!=null&&i.is_pending&&t.f&(Ia|Wn|vr)&&!(t.f&fa)){t.b.defer_effect(t);return}for(var e=t;e.parent!==null;){e=e.parent;var n=e.f;if(ya!==null&&e===Ae&&(Me===null||!(Me.f&Tt))&&!si)return;if(n&(Ks|fs)){if(!(n&pt))return;e.f^=pt}}m(this,jt).push(e)}};Ta=new WeakMap,Ws=new WeakMap,ta=new WeakMap,Ea=new WeakMap,Sa=new WeakMap,sa=new WeakMap,Aa=new WeakMap,As=new WeakMap,en=new WeakMap,jt=new WeakMap,tn=new WeakMap,zs=new WeakMap,ms=new WeakMap,ys=new WeakMap,Ca=new WeakMap,Pa=new WeakMap,Fe=new WeakSet,ii=function(){if(this.is_fork)return!0;for(const n of m(this,As).keys()){for(var t=n,e=!1;t.parent!==null;){if(m(this,ys).has(t)){e=!0;break}t=t.parent}if(!e)return!0}return!1},ja=function(){var d,p,_,h;if(xe(this,Ta,!0),zi++>1e3&&(Re(this,Fe,ma).call(this),no()),!Re(this,Fe,ii).call(this)){for(const v of m(this,zs))m(this,ms).delete(v),at(v,mt),this.schedule(v);for(const v of m(this,ms))at(v,ks),this.schedule(v)}const t=m(this,jt);xe(this,jt,[]),this.apply();var e=ya=[],n=[],i=wn=[];for(const v of t)try{Re(this,Fe,ri).call(this,v,e,n)}catch(x){throw Er(v),x}if(fe=null,i.length>0){var l=Ln.ensure();for(const v of i)l.schedule(v)}if(ya=null,wn=null,Re(this,Fe,ii).call(this)){Re(this,Fe,xn).call(this,n),Re(this,Fe,xn).call(this,e);for(const[v,x]of m(this,ys))Tr(v,x);i.length>0&&Re(d=fe,Fe,ja).call(d);return}const c=Re(this,Fe,wr).call(this);if(c){Re(p=c,Fe,xr).call(p,this);return}m(this,zs).clear(),m(this,ms).clear();for(const v of m(this,Ea))v(this);m(this,Ea).clear(),$a=this,qi(n),qi(e),$a=null,(_=m(this,en))==null||_.resolve();var u=fe;if(this.linked&&m(this,Aa)===0&&Re(this,Fe,ma).call(this),m(this,jt).length>0){u===null&&(u=this,Re(this,Fe,li).call(this));const v=u;m(v,jt).push(...m(this,jt).filter(x=>!m(v,jt).includes(x)))}u!==null&&Re(h=u,Fe,ja).call(h)},ri=function(t,e,n){t.f^=pt;for(var i=t.first;i!==null;){var l=i.f,c=(l&(fs|Ks))!==0,u=c&&(l&pt)!==0,d=u||(l&It)!==0||m(this,ys).has(i);if(!d&&i.fn!==null){c?i.f^=pt:l&Ia?e.push(i):dn(i)&&(l&ds&&m(this,ms).add(i),Ra(i));var p=i.first;if(p!==null){i=p;continue}}for(;i!==null;){var _=i.next;if(_!==null){i=_;break}i=i.parent}}},wr=function(){for(var t=m(this,Ws);t!==null;){if(!t.is_fork){for(const[e,[,n]]of this.current)if(t.current.has(e)&&!n)return t}t=m(t,Ws)}return null},xr=function(t){var n;for(const[i,l]of t.current)!this.previous.has(i)&&t.previous.has(i)&&this.previous.set(i,t.previous.get(i)),this.current.set(i,l);for(const[i,l]of t.async_deriveds){const c=this.async_deriveds.get(i);c&&l.promise.then(c.resolve)}const e=i=>{var l=i.reactions;if(l!==null)for(const d of l){var c=d.f;if(c&Tt)e(d);else{var u=d;c&(xa|ds)&&!this.async_deriveds.has(u)&&(m(this,ms).delete(u),at(u,mt),this.schedule(u))}}};for(const i of this.current.keys())e(i);this.oncommit(()=>t.discard()),Re(n=t,Fe,ma).call(n),fe=this,Re(this,Fe,ja).call(this)},xn=function(t){for(var e=0;e!this.current.has(v));if(i.length===0)t&&h.discard();else if(e.length>0){if(t)for(const v of m(this,Ca))h.unskip_effect(v,x=>{var y;x.f&(ds|xa)?h.schedule(x):Re(y=h,Fe,xn).call(y,[x])});h.activate();var l=new Set,c=new Map;for(var u of e)kr(u,i,l,c);c=new Map;var d=[...h.current.keys()].filter(v=>this.current.has(v)?this.current.get(v)[0]!==v.v:!0);if(d.length>0)for(const v of m(this,tn))!(v.f&(ns|It|Cn))&&wi(v,d,c)&&(v.f&(xa|ds)?(at(v,mt),h.schedule(v)):m(h,zs).add(v));if(m(h,jt).length>0){h.apply();for(var p of m(h,jt))Re(_=h,Fe,ri).call(_,p,[],[]);xe(h,jt,[])}h.deactivate()}}}},li=function(){_a===null?jn=_a=this:(xe(_a,ta,this),xe(this,Ws,_a)),_a=this},ma=function(){var t=m(this,Ws),e=m(this,ta);t===null?jn=e:xe(t,ta,e),e===null?_a=t:xe(e,Ws,t),this.linked=!1};let va=Ln;function ao(s){var t=Ya;Ya=!0;try{for(var e;;){if(Gl(),fe===null)return e;fe.flush()}}finally{Ya=t}}function no(){try{Vl()}catch(s){Vs(s,ni)}}let cs=null;function qi(s){var t=s.length;if(t!==0){for(var e=0;e0)){ra.clear();for(const i of cs){if(i.f&(ns|It))continue;const l=[i];let c=i.parent;for(;c!==null;)cs.has(c)&&(cs.delete(c),l.push(c)),c=c.parent;for(let u=l.length-1;u>=0;u--){const d=l[u];d.f&(ns|It)||Ra(d)}}cs.clear()}}cs=null}}function kr(s,t,e,n){if(!e.has(s)&&(e.add(s),s.reactions!==null))for(const i of s.reactions){const l=i.f;l&Tt?kr(i,t,e,n):l&(xa|ds)&&!(l&mt)&&wi(i,t,n)&&(at(i,mt),xi(i))}}function wi(s,t,e){const n=e.get(s);if(n!==void 0)return n;if(s.deps!==null)for(const i of s.deps){if(Oa.call(t,i))return!0;if(i.f&Tt&&wi(i,t,e))return e.set(i,!0),!0}return e.set(s,!1),!1}function xi(s){fe.schedule(s)}function Tr(s,t){if(!(s.f&fs&&s.f&pt)){s.f&mt?t.d.push(s):s.f&ks&&t.m.push(s),at(s,pt);for(var e=s.first;e!==null;)Tr(e,t),e=e.next}}function Er(s){at(s,pt);for(var t=s.first;t!==null;)Er(t),t=t.next}function io(s){let t=0,e=pa(0),n;return()=>{Ei()&&(a(e),Vn(()=>(t===0&&(n=Ns(()=>s(()=>Ga(e)))),t+=1,()=>{js(()=>{t-=1,t===0&&(n==null||n(),n=void 0,Ga(e))})})))}}var ro=Da|za;function lo(s,t,e,n){new oo(s,t,e,n)}var Xt,bi,Qt,aa,Nt,es,Ot,Ht,Cs,na,qs,Ma,sn,an,Ps,Nn,it,co,uo,vo,oi,kn,Tn,ci,ui;class oo{constructor(t,e,n,i){Te(this,it);Lt(this,"parent");Lt(this,"is_pending",!1);Lt(this,"transform_error");Te(this,Xt);Te(this,bi,null);Te(this,Qt);Te(this,aa);Te(this,Nt);Te(this,es,null);Te(this,Ot,null);Te(this,Ht,null);Te(this,Cs,null);Te(this,na,0);Te(this,qs,0);Te(this,Ma,!1);Te(this,sn,new Set);Te(this,an,new Set);Te(this,Ps,null);Te(this,Nn,io(()=>(xe(this,Ps,pa(m(this,na))),()=>{xe(this,Ps,null)})));var l,c;xe(this,Xt,t),xe(this,Qt,e),xe(this,aa,u=>{var d=Ae;d.b=this,d.f|=Xn,n(u)}),this.parent=Ae.b,this.transform_error=(c=i!=null?i:(l=this.parent)==null?void 0:l.transform_error)!=null?c:u=>u,xe(this,Nt,Ai(()=>{Re(this,it,oi).call(this)},ro))}defer_effect(t){yr(t,m(this,sn),m(this,an))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!m(this,Qt).pending}update_pending_count(t,e){Re(this,it,ci).call(this,t,e),xe(this,na,m(this,na)+t),!(!m(this,Ps)||m(this,Ma))&&(xe(this,Ma,!0),js(()=>{xe(this,Ma,!1),m(this,Ps)&&Na(m(this,Ps),m(this,na))}))}get_effect_pending(){return m(this,Nn).call(this),a(m(this,Ps))}error(t){if(!m(this,Qt).onerror&&!m(this,Qt).failed)throw t;fe!=null&&fe.is_fork?(m(this,es)&&fe.skip_effect(m(this,es)),m(this,Ot)&&fe.skip_effect(m(this,Ot)),m(this,Ht)&&fe.skip_effect(m(this,Ht)),fe.on_fork_commit(()=>{Re(this,it,ui).call(this,t)})):Re(this,it,ui).call(this,t)}}Xt=new WeakMap,bi=new WeakMap,Qt=new WeakMap,aa=new WeakMap,Nt=new WeakMap,es=new WeakMap,Ot=new WeakMap,Ht=new WeakMap,Cs=new WeakMap,na=new WeakMap,qs=new WeakMap,Ma=new WeakMap,sn=new WeakMap,an=new WeakMap,Ps=new WeakMap,Nn=new WeakMap,it=new WeakSet,co=function(){try{xe(this,es,ts(()=>m(this,aa).call(this,m(this,Xt))))}catch(t){this.error(t)}},uo=function(t){const e=m(this,Qt).failed;e&&xe(this,Ht,ts(()=>{e(m(this,Xt),()=>t,()=>()=>{})}))},vo=function(){const t=m(this,Qt).pending;t&&(this.is_pending=!0,xe(this,Ot,ts(()=>t(m(this,Xt)))),js(()=>{var e=xe(this,Cs,document.createDocumentFragment()),n=Is();e.append(n),xe(this,es,Re(this,it,Tn).call(this,()=>ts(()=>m(this,aa).call(this,n)))),m(this,qs)===0&&(m(this,Xt).before(e),xe(this,Cs,null),oa(m(this,Ot),()=>{xe(this,Ot,null)}),Re(this,it,kn).call(this,fe))}))},oi=function(){try{if(this.is_pending=this.has_pending_snippet(),xe(this,qs,0),xe(this,na,0),xe(this,es,ts(()=>{m(this,aa).call(this,m(this,Xt))})),m(this,qs)>0){var t=xe(this,Cs,document.createDocumentFragment());Mi(m(this,es),t);const e=m(this,Qt).pending;xe(this,Ot,ts(()=>e(m(this,Xt))))}else Re(this,it,kn).call(this,fe)}catch(e){this.error(e)}},kn=function(t){this.is_pending=!1,t.transfer_effects(m(this,sn),m(this,an))},Tn=function(t){var e=Ae,n=Me,i=nt;Ts(m(this,Nt)),rs(m(this,Nt)),La(m(this,Nt).ctx);try{return va.ensure(),t()}catch(l){return br(l),null}finally{Ts(e),rs(n),La(i)}},ci=function(t,e){var n;if(!this.has_pending_snippet()){this.parent&&Re(n=this.parent,it,ci).call(n,t,e);return}xe(this,qs,m(this,qs)+t),m(this,qs)===0&&(Re(this,it,kn).call(this,e),m(this,Ot)&&oa(m(this,Ot),()=>{xe(this,Ot,null)}),m(this,Cs)&&(m(this,Xt).before(m(this,Cs)),xe(this,Cs,null)))},ui=function(t){m(this,es)&&(Ft(m(this,es)),xe(this,es,null)),m(this,Ot)&&(Ft(m(this,Ot)),xe(this,Ot,null)),m(this,Ht)&&(Ft(m(this,Ht)),xe(this,Ht,null));var e=m(this,Qt).onerror;let n=m(this,Qt).failed;var i=!1,l=!1;const c=()=>{if(i){Yl();return}i=!0,l&&Kl(),m(this,Ht)!==null&&oa(m(this,Ht),()=>{xe(this,Ht,null)}),Re(this,it,Tn).call(this,()=>{Re(this,it,oi).call(this)})},u=d=>{try{l=!0,e==null||e(d,c),l=!1}catch(p){Vs(p,m(this,Nt)&&m(this,Nt).parent)}n&&xe(this,Ht,Re(this,it,Tn).call(this,()=>{try{return ts(()=>{var p=Ae;p.b=this,p.f|=Xn,n(m(this,Xt),()=>d,()=>c)})}catch(p){return Vs(p,m(this,Nt).parent),null}}))};js(()=>{var d;try{d=this.transform_error(t)}catch(p){Vs(p,m(this,Nt)&&m(this,Nt).parent);return}d!==null&&typeof d=="object"&&typeof d.then=="function"?d.then(u,p=>Vs(p,m(this,Nt)&&m(this,Nt).parent)):u(d)})};function po(s,t,e,n){const i=ln()?Za:ki;var l=s.filter(v=>!v.settled);if(e.length===0&&l.length===0){n(t.map(i));return}var c=Ae,u=fo(),d=l.length===1?l[0].promise:l.length>1?Promise.all(l.map(v=>v.promise)):null;function p(v){if(!(c.f&ns)){u();try{n(v)}catch(x){Vs(x,c)}Mn()}}var _=Sr();if(e.length===0){d.then(()=>p(t.map(i))).finally(_);return}function h(){Promise.all(e.map(v=>ho(v))).then(v=>p([...t.map(i),...v])).catch(v=>Vs(v,c)).finally(_)}d?d.then(()=>{u(),h(),Mn()}):h()}function fo(){var s=Ae,t=Me,e=nt,n=fe;return function(l=!0){Ts(s),rs(t),La(e),l&&!(s.f&ns)&&(n==null||n.activate(),n==null||n.apply())}}function Mn(s=!0){Ts(null),rs(null),La(null),s&&(fe==null||fe.deactivate())}function Sr(){var s=Ae,t=s.b,e=fe,n=t.is_rendered();return t.update_pending_count(1,e),e.increment(n,s),()=>{t.update_pending_count(-1,e),e.decrement(n,s)}}function Za(s){var t=Tt|mt;return Ae!==null&&(Ae.f|=za),{ctx:nt,deps:null,effects:null,equals:fr,f:t,fn:s,reactions:null,rv:0,v:vt,wv:0,parent:Ae,ac:null}}const _n=Symbol("obsolete");function ho(s,t,e){let n=Ae;n===null&&Rl();var i=void 0,l=pa(vt),c=!Me,u=new Set;return Eo(()=>{var x;var d=Ae,p=dr();i=p.promise;try{Promise.resolve(s()).then(p.resolve,y=>{y!==zn&&p.reject(y)}).finally(Mn)}catch(y){p.reject(y),Mn()}var _=fe;if(c){if(d.f&fa)var h=Sr();if(n.b.is_rendered())(x=_.async_deriveds.get(d))==null||x.reject(_n);else for(const y of u.values())y.reject(_n);u.add(p),_.async_deriveds.set(d,p)}const v=(y,C=void 0)=>{h==null||h(),u.delete(p),C!==_n&&(_.activate(),C?(l.f|=Us,Na(l,C)):(l.f&Us&&(l.f^=Us),Na(l,y)),_.deactivate())};p.promise.then(v,y=>v(null,y||"unknown"))}),Si(()=>{for(const d of u)d.reject(_n)}),new Promise(d=>{function p(_){function h(){_===i?d(l):p(i)}_.then(h,h)}p(i)})}function he(s){const t=Za(s);return jr(t),t}function ki(s){const t=Za(s);return t.equals=_r,t}function _o(s){var t=s.effects;if(t!==null){s.effects=null;for(var e=0;e0&&!Pr&&bo()}return t}function bo(){Pr=!1;for(const s of On){s.f&pt&&at(s,ks);let t;try{t=dn(s)}catch{t=!0}t&&Ra(s)}On.clear()}function Ga(s){f(s,s.v+1)}function Or(s,t,e){var n=s.reactions;if(n!==null)for(var i=ln(),l=n.length,c=0;c{if(ca===l)return u();var d=Me,p=ca;rs(null),ji(l);var _=u();return rs(d),ji(p),_};return n&&e.set("length",B(s.length)),new Proxy(s,{defineProperty(u,d,p){(!("value"in p)||p.configurable===!1||p.enumerable===!1||p.writable===!1)&&Ul();var _=e.get(d);return _===void 0?c(()=>{var h=B(p.value);return e.set(d,h),h}):f(_,p.value,!0),!0},deleteProperty(u,d){var p=e.get(d);if(p===void 0){if(d in u){const _=c(()=>B(vt));e.set(d,_),Ga(i)}}else f(p,vt),Ga(i);return!0},get(u,d,p){var x;if(d===Ka)return s;var _=e.get(d),h=d in u;if(_===void 0&&(!h||(x=wa(u,d))!=null&&x.writable)&&(_=c(()=>{var y=Be(h?u[d]:vt),C=B(y);return C}),e.set(d,_)),_!==void 0){var v=a(_);return v===vt?void 0:v}return Reflect.get(u,d,p)},getOwnPropertyDescriptor(u,d){var p=Reflect.getOwnPropertyDescriptor(u,d);if(p&&"value"in p){var _=e.get(d);_&&(p.value=a(_))}else if(p===void 0){var h=e.get(d),v=h==null?void 0:h.v;if(h!==void 0&&v!==vt)return{enumerable:!0,configurable:!0,value:v,writable:!0}}return p},has(u,d){var v;if(d===Ka)return!0;var p=e.get(d),_=p!==void 0&&p.v!==vt||Reflect.has(u,d);if(p!==void 0||Ae!==null&&(!_||(v=wa(u,d))!=null&&v.writable)){p===void 0&&(p=c(()=>{var x=_?Be(u[d]):vt,y=B(x);return y}),e.set(d,p));var h=a(p);if(h===vt)return!1}return _},set(u,d,p,_){var V;var h=e.get(d),v=d in u;if(n&&d==="length")for(var x=p;xB(vt)),e.set(x+"",y))}if(h===void 0)(!v||(V=wa(u,d))!=null&&V.writable)&&(h=c(()=>B(void 0)),f(h,Be(p)),e.set(d,h));else{v=h.v!==vt;var C=c(()=>Be(p));f(h,C)}var k=Reflect.getOwnPropertyDescriptor(u,d);if(k!=null&&k.set&&k.set.call(_,p),!v){if(n&&typeof d=="string"){var S=e.get("length"),D=Number(d);Number.isInteger(D)&&D>=S.v&&f(S,D+1)}Ga(i)}return!0},ownKeys(u){a(i);var d=Reflect.ownKeys(u).filter(h=>{var v=e.get(h);return v===void 0||v.v!==vt});for(var[p,_]of e)_.v!==vt&&!(p in u)&&d.push(p);return d},setPrototypeOf(){jl()}})}var Vi,Ir,Dr,Lr;function mo(){if(Vi===void 0){Vi=window,Ir=/Firefox/.test(navigator.userAgent);var s=Element.prototype,t=Node.prototype,e=Text.prototype;Dr=wa(t,"firstChild").get,Lr=wa(t,"nextSibling").get,Wi(s)&&(s[ei]=void 0,s[mn]=null,s[ti]=void 0,s.__e=void 0),Wi(e)&&(e[Ba]=void 0)}}function Is(s=""){return document.createTextNode(s)}function Bs(s){return Dr.call(s)}function un(s){return Lr.call(s)}function o(s,t){return Bs(s)}function Ct(s,t=!1){{var e=Bs(s);return e instanceof Comment&&e.data===""?un(e):e}}function r(s,t=1,e=!1){let n=s;for(;t--;)n=un(n);return n}function yo(s){s.textContent=""}function Nr(){return!1}function Rr(s,t,e){return document.createElementNS(t!=null?t:ir,s,void 0)}let Bi=!1;function wo(){Bi||(Bi=!0,document.addEventListener("reset",s=>{Promise.resolve().then(()=>{var t;if(!s.defaultPrevented)for(const e of s.target.elements)(t=e[yn])==null||t.call(e)})},{capture:!0}))}function qn(s){var t=Me,e=Ae;rs(null),Ts(null);try{return s()}finally{rs(t),Ts(e)}}function Fr(s,t,e,n=e){s.addEventListener(t,()=>qn(e));const i=s[yn];i?s[yn]=()=>{i(),n(!0)}:s[yn]=()=>n(!0),wo()}function xo(s){Ae===null&&(Me===null&&ql(),zl()),Ds&&Wl()}function ko(s,t){var e=t.last;e===null?t.last=t.first=s:(e.next=s,s.prev=e,t.last=s)}function Ls(s,t){var c;var e=Ae;e!==null&&e.f&It&&(s|=It);var n={ctx:nt,deps:null,nodes:null,f:s|mt|as,first:null,fn:t,last:null,next:null,parent:e,b:e&&e.b,prev:null,teardown:null,wv:0,ac:null};fe==null||fe.register_created_effect(n);var i=n;if(s&Ia)ya!==null?ya.push(n):va.ensure().schedule(n);else if(t!==null){try{Ra(n)}catch(u){throw Ft(n),u}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&za)&&(i=i.first,s&ds&&s&Da&&i!==null&&(i.f|=Da))}if(i!==null&&(i.parent=e,e!==null&&ko(i,e),Me!==null&&Me.f&Tt&&!(s&Ks))){var l=Me;((c=l.effects)!=null?c:l.effects=[]).push(i)}return n}function Ei(){return Me!==null&&!vs}function Si(s){const t=Ls(Wn,null);return at(t,pt),t.teardown=s,t}function ka(s){var i;xo();var t=Ae.f,e=!Me&&(t&fs)!==0&&(t&fa)===0;if(e){var n=nt;((i=n.e)!=null?i:n.e=[]).push(s)}else return Wr(s)}function Wr(s){return Ls(Ia|Il,s)}function To(s){va.ensure();const t=Ls(Ks|za,s);return(e={})=>new Promise(n=>{e.outro?oa(t,()=>{Ft(t),n(void 0)}):(Ft(t),n(void 0))})}function la(s){return Ls(Ia,s)}function Eo(s){return Ls(xa|za,s)}function Vn(s,t=0){return Ls(Wn|t,s)}function G(s,t=[],e=[],n=[]){po(n,t,e,i=>{Ls(Wn,()=>s(...i.map(a)))})}function Ai(s,t=0){var e=Ls(ds|t,s);return e}function ts(s){return Ls(fs|za,s)}function zr(s){var t=s.teardown;if(t!==null){const e=Ds,n=Me;Ui(!0),rs(null);try{t.call(null)}finally{Ui(e),rs(n)}}}function Ci(s,t=!1){var e=s.first;for(s.first=s.last=null;e!==null;){const i=e.ac;i!==null&&qn(()=>{i.abort(zn)});var n=e.next;e.f&Ks?e.parent=null:Ft(e,t),e=n}}function So(s){for(var t=s.first;t!==null;){var e=t.next;t.f&fs||Ft(t),t=e}}function Ft(s,t=!0){var e=!1;(t||s.f&Ol)&&s.nodes!==null&&s.nodes.end!==null&&(qr(s.nodes.start,s.nodes.end),e=!0),at(s,Qn),Ci(s,t&&!e),Xa(s,0);var n=s.nodes&&s.nodes.t;if(n!==null)for(const l of n)l.stop();zr(s),s.f^=Qn,s.f|=ns;var i=s.parent;i!==null&&i.first!==null&&Vr(s),s.next=s.prev=s.teardown=s.ctx=s.deps=s.fn=s.nodes=s.ac=s.b=null}function qr(s,t){for(;s!==null;){var e=s===t?null:un(s);s.remove(),s=e}}function Vr(s){var t=s.parent,e=s.prev,n=s.next;e!==null&&(e.next=n),n!==null&&(n.prev=e),t!==null&&(t.first===s&&(t.first=n),t.last===s&&(t.last=e))}function oa(s,t,e=!0){var n=[];Br(s,n,!0);var i=()=>{e&&Ft(s),t&&t()},l=n.length;if(l>0){var c=()=>--l||i();for(var u of n)u.out(c)}else i()}function Br(s,t,e){if(!(s.f&It)){s.f^=It;var n=s.nodes&&s.nodes.t;if(n!==null)for(const u of n)(u.is_global||e)&&t.push(u);for(var i=s.first;i!==null;){var l=i.next;if(!(i.f&Ks)){var c=(i.f&Da)!==0||(i.f&fs)!==0&&(s.f&ds)!==0;Br(i,t,c?e:!1)}i=l}}}function Pi(s){Ur(s,!0)}function Ur(s,t){if(s.f&It){s.f^=It,s.f&pt||(at(s,mt),va.ensure().schedule(s));for(var e=s.first;e!==null;){var n=e.next,i=(e.f&Da)!==0||(e.f&fs)!==0;Ur(e,i?t:!1),e=n}var l=s.nodes&&s.nodes.t;if(l!==null)for(const c of l)(c.is_global||t)&&c.in()}}function Mi(s,t){if(s.nodes)for(var e=s.nodes.start,n=s.nodes.end;e!==null;){var i=e===n?null:un(e);t.append(e),e=i}}let En=!1,Ds=!1;function Ui(s){Ds=s}let Me=null,vs=!1;function rs(s){Me=s}let Ae=null;function Ts(s){Ae=s}let is=null;function jr(s){Me!==null&&(is===null?is=[s]:is.push(s))}let Rt=null,Bt=0,Zt=null;function Ao(s){Zt=s}let Hr=1,Qs=0,ca=Qs;function ji(s){ca=s}function Kr(){return++Hr}function dn(s){var t=s.f;if(t&mt)return!0;if(t&Tt&&(s.f&=~da),t&ks){for(var e=s.deps,n=e.length,i=0;is.wv)return!0}t&as&&xt===null&&at(s,pt)}return!1}function $r(s,t,e=!0){var n=s.reactions;if(n!==null&&!(is!==null&&Oa.call(is,s)))for(var i=0;i{s.ac.abort(zn)}),s.ac=null);try{s.f|=Pn;var _=s.fn,h=_();s.f|=fa;var v=s.deps,x=fe==null?void 0:fe.is_fork;if(Rt!==null){var y;if(x||Xa(s,Bt),v!==null&&Bt>0)for(v.length=Bt+Rt.length,y=0;ye==null?void 0:e.call(this,l))}return s.startsWith("pointer")||s.startsWith("touch")||s==="wheel"?js(()=>{t.addEventListener(s,i,n)}):t.addEventListener(s,i,n),i}function Ms(s,t,e,n,i){var l={capture:n,passive:i},c=Mo(s,t,e,l);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&Si(()=>{t.removeEventListener(s,c,l)})}function K(s,t,e){var n;((n=t[ea])!=null?n:t[ea]={})[s]=e}function Wt(s){for(var t=0;t{throw D});throw v}}finally{s[ea]=t,delete s.currentTarget,rs(_),Ts(h)}}}var ar;const Kn=((ar=globalThis==null?void 0:globalThis.window)==null?void 0:ar.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:s=>s});function Oo(s){var t;return(t=Kn==null?void 0:Kn.createHTML(s))!=null?t:s}function Io(s){var t=Rr("template");return t.innerHTML=Oo(s.replaceAll("","")),t.content}function Fa(s,t){var e=Ae;e.nodes===null&&(e.nodes={start:s,end:t,a:null,t:null})}function E(s,t){var e=(t&kl)!==0,n=(t&Tl)!==0,i,l=!s.startsWith("");return()=>{i===void 0&&(i=Io(l?s:""+s),e||(i=Bs(i)));var c=n||Ir?document.importNode(i,!0):i.cloneNode(!0);if(e){var u=Bs(c),d=c.lastChild;Fa(u,d)}else Fa(c,c);return c}}function Ee(s=""){{var t=Is(s+"");return Fa(t,t),t}}function Xr(){var s=document.createDocumentFragment(),t=document.createComment(""),e=Is();return s.append(t,e),Fa(t,e),s}function g(s,t){s!==null&&s.before(t)}const Do=["touchstart","touchmove"];function Lo(s){return Do.includes(s)}function X(s,t){var n;var e=t==null?"":typeof t=="object"?`${t}`:t;e!==((n=s[Ba])!=null?n:s[Ba]=s.nodeValue)&&(s[Ba]=e,s.nodeValue=`${e}`)}function No(s,t){return Ro(s,t)}const gn=new Map;function Ro(s,{target:t,anchor:e,props:n={},events:i,context:l,intro:c=!0,transformError:u}){mo();var d=void 0,p=To(()=>{var _=e!=null?e:t.appendChild(Is());lo(_,{pending:()=>{}},x=>{$e({});var y=nt;l&&(y.c=l),i&&(n.$$events=i),d=s(x,n)||{},Ye()},u);var h=new Set,v=x=>{for(var y=0;y{var k;for(var x of h)for(const S of[t,document]){var y=gn.get(S),C=y.get(x);--C==0?(S.removeEventListener(x,vi),y.delete(x),y.size===0&&gn.delete(S)):y.set(x,C)}di.delete(v),_!==e&&((k=_.parentNode)==null||k.removeChild(_))}});return Fo.set(d,p),d}let Fo=new WeakMap;var us,ws,Kt,ia,nn,rn,Rn;class Wo{constructor(t,e=!0){Lt(this,"anchor");Te(this,us,new Map);Te(this,ws,new Map);Te(this,Kt,new Map);Te(this,ia,new Set);Te(this,nn,!0);Te(this,rn,t=>{if(m(this,us).has(t)){var e=m(this,us).get(t),n=m(this,ws).get(e);if(n)Pi(n),m(this,ia).delete(e);else{var i=m(this,Kt).get(e);i&&(m(this,ws).set(e,i.effect),m(this,Kt).delete(e),i.fragment.lastChild.remove(),this.anchor.before(i.fragment),n=i.effect)}for(const[l,c]of m(this,us)){if(m(this,us).delete(l),l===t)break;const u=m(this,Kt).get(c);u&&(Ft(u.effect),m(this,Kt).delete(c))}for(const[l,c]of m(this,ws)){if(l===e||m(this,ia).has(l))continue;const u=()=>{if(Array.from(m(this,us).values()).includes(l)){var p=document.createDocumentFragment();Mi(c,p),p.append(Is()),m(this,Kt).set(l,{effect:c,fragment:p})}else Ft(c);m(this,ia).delete(l),m(this,ws).delete(l)};m(this,nn)||!n?(m(this,ia).add(l),oa(c,u,!1)):u()}}});Te(this,Rn,t=>{m(this,us).delete(t);const e=Array.from(m(this,us).values());for(const[n,i]of m(this,Kt))e.includes(n)||(Ft(i.effect),m(this,Kt).delete(n))});this.anchor=t,xe(this,nn,e)}ensure(t,e){var n=fe,i=Nr();if(e&&!m(this,ws).has(t)&&!m(this,Kt).has(t))if(i){var l=document.createDocumentFragment(),c=Is();l.append(c),m(this,Kt).set(t,{effect:ts(()=>e(c)),fragment:l})}else m(this,ws).set(t,ts(()=>e(this.anchor)));if(m(this,us).set(n,t),i){for(const[u,d]of m(this,ws))u===t?n.unskip_effect(d):n.skip_effect(d);for(const[u,d]of m(this,Kt))u===t?n.unskip_effect(d.effect):n.skip_effect(d.effect);n.oncommit(m(this,rn)),n.ondiscard(m(this,Rn))}else m(this,rn).call(this,n)}}us=new WeakMap,ws=new WeakMap,Kt=new WeakMap,ia=new WeakMap,nn=new WeakMap,rn=new WeakMap,Rn=new WeakMap;function rt(s){nt===null&&pr(),Wa&&nt.l!==null?zo(nt).m.push(s):ka(()=>{const t=Ns(s);if(typeof t=="function")return t})}function Qr(s){nt===null&&pr(),rt(()=>()=>Ns(s))}function zo(s){var e;var t=s.l;return(e=t.u)!=null?e:t.u={a:[],b:[],m:[]}}function U(s,t,e=!1){var n=new Wo(s),i=e?Da:0;function l(c,u){n.ensure(c,u)}Ai(()=>{var c=!1;t((u,d=0)=>{c=!0,l(d,u)}),c||l(-1,null)},i)}function ft(s,t){return t}function qo(s,t,e){var h;for(var n=[],i=t.length,l,c=t.length,u=0;u{if(l){if(l.pending.delete(v),l.done.add(v),l.pending.size===0){var x=s.outrogroups;pi(s,Fn(l.done)),x.delete(l),x.size===0&&(s.outrogroups=null)}}else c-=1},!1)}if(c===0){var d=n.length===0&&e!==null;if(d){var p=e,_=p.parentNode;yo(_),_.append(p),s.items.clear()}pi(s,t,!d)}else l={pending:new Set(t),done:new Set},((h=s.outrogroups)!=null?h:s.outrogroups=new Set).add(l)}function pi(s,t,e=!0){var n;if(s.pending.size>0){n=new Set;for(const c of s.pending.values())for(const u of c)n.add(s.items.get(u).e)}for(var i=0;i{var V=e();return lr(V)?V:V==null?[]:Fn(V)}),v,x=new Map,y=!0;function C(V){D.effect.f&ns||(D.pending.delete(V),D.fallback=_,Vo(D,v,c,t,n),_!==null&&(v.length===0?_.f&xs?(_.f^=xs,Ha(_,null,c)):Pi(_):oa(_,()=>{_=null})))}function k(V){D.pending.delete(V)}var S=Ai(()=>{v=a(h);for(var V=v.length,$=new Set,F=fe,b=Nr(),L=0;Ll(c)):(_=ts(()=>l(ga!=null?ga:ga=Is())),_.f|=xs)),V>$.size&&Fl(),!y)if(x.set(F,$),b){for(const[ue,w]of u)$.has(ue)||F.skip_effect(w.e);F.oncommit(C),F.ondiscard(k)}else C(F);a(h)}),D={effect:S,items:u,pending:x,outrogroups:null,fallback:_};y=!1}function Va(s){for(;s!==null&&!(s.f&fs);)s=s.next;return s}function Vo(s,t,e,n,i){var oe,ue,w,J,q,N,M,j,z;var l=(n&_l)!==0,c=t.length,u=s.items,d=Va(s.effect.first),p,_=null,h,v=[],x=[],y,C,k,S;if(l)for(S=0;S0){var se=n&nr&&c===0?e:null;if(l){for(S=0;S{var I,Q;if(h!==void 0)for(k of h)(Q=(I=k.nodes)==null?void 0:I.a)==null||Q.apply()})}function Bo(s,t,e,n,i,l,c,u){var d=c&fl?c&gl?pa(e):Mr(e,!1,!1):null,p=c&hl?pa(i):null;return{v:d,i:p,e:ts(()=>(l(t,d!=null?d:e,p!=null?p:i,u),()=>{s.delete(n)}))}}function Ha(s,t,e){if(s.nodes)for(var n=s.nodes.start,i=s.nodes.end,l=t&&!(t.f&xs)?t.nodes.start:e;n!==null;){var c=un(n);if(l.before(n),n===i)return;n=c}}function Fs(s,t,e){t===null?s.effect.first=e:t.next=e,e===null?s.effect.last=t:e.prev=t}function Ki(s,t,e=!1,n=!1,i=!1,l=!1){var c=s,u="";if(e)var d=s;G(()=>{var x;var p=Ae;if(u!==(u=(x=t())!=null?x:"")){if(e){p.nodes=null,d.innerHTML=u,u!==""&&Fa(Bs(d),d.lastChild);return}if(p.nodes!==null&&(qr(p.nodes.start,p.nodes.end),p.nodes=null),u!==""){var _=n?El:i?Sl:void 0,h=Rr(n?"svg":i?"math":"template",_);h.innerHTML=u;var v=n||i?h:h.content;if(Fa(Bs(v),v.lastChild),n||i)for(;Bs(v);)c.before(Bs(v));else c.before(v)}}})}function ua(s,t,e){la(()=>{var n=Ns(()=>t(s,e==null?void 0:e())||{});if(n!=null&&n.destroy)return()=>n.destroy()})}function el(s){var t,e,n="";if(typeof s=="string"||typeof s=="number")n+=s;else if(typeof s=="object")if(Array.isArray(s)){var i=s.length;for(t=0;t=0;){var u=c+l;(c===0||$i.includes(n[c-1]))&&(u===n.length||$i.includes(n[u]))?n=(c===0?"":n.substring(0,c))+n.substring(u+1):c=u}}return n===""?null:n}function Ho(s,t){return s==null?null:String(s)}function ye(s,t,e,n,i,l){var c=s[ei];if(c!==e||c===void 0){var u=jo(e,n,l);u==null?s.removeAttribute("class"):s.className=u,s[ei]=e}else if(l&&i!==l)for(var d in l){var p=!!l[d];(i==null||p!==!!i[d])&&s.classList.toggle(d,p)}return l}function $s(s,t,e,n){var i=s[ti];if(i!==t){var l=Ho(t);l==null?s.removeAttribute("style"):s.style.cssText=l,s[ti]=t}return n}const Ko=Symbol("is custom element"),$o=Symbol("is html"),Yo=Nl?"progress":"PROGRESS";function Go(s,t){var e=tl(s);e.value===(e.value=t!=null?t:void 0)||s.value===t&&(t!==0||s.nodeName!==Yo)||(s.value=t!=null?t:"")}function _t(s,t,e,n){var i=tl(s);i[t]!==(i[t]=e)&&(t==="loading"&&(s[Ll]=e),e==null?s.removeAttribute(t):typeof e!="string"&&Jo(s).includes(t)?s[t]=e:s.setAttribute(t,e))}function tl(s){var t;return(t=s[mn])!=null?t:s[mn]={[Ko]:s.nodeName.includes("-"),[$o]:s.namespaceURI===ir}}var Yi=new Map;function Jo(s){var t=s.getAttribute("is")||s.nodeName,e=Yi.get(t);if(e)return e;Yi.set(t,e=[]);for(var n,i=s,l=Element.prototype;l!==i;){n=Cl(i);for(var c in n)n[c].set&&c!=="innerHTML"&&c!=="textContent"&&c!=="innerText"&&e.push(c);i=cr(i)}return e}function ge(s,t,e=t){var n=new WeakSet;Fr(s,"input",async i=>{var l=i?s.defaultValue:s.value;if(l=$n(s)?Yn(l):l,e(l),fe!==null&&n.add(fe),await Po(),l!==(l=t())){var c=s.selectionStart,u=s.selectionEnd,d=s.value.length;if(s.value=l!=null?l:"",u!==null){var p=s.value.length;c===u&&u===d&&p>d?(s.selectionStart=p,s.selectionEnd=p):(s.selectionStart=c,s.selectionEnd=Math.min(u,p))}}}),Ns(t)==null&&s.value&&(e($n(s)?Yn(s.value):s.value),fe!==null&&n.add(fe)),Vn(()=>{var i=t();if(s===document.activeElement){var l=fe;if(n.has(l))return}$n(s)&&i===Yn(s.value)||s.type==="date"&&!i&&!s.value||i!==s.value&&(s.value=i!=null?i:"")})}function Xe(s,t,e=t){Fr(s,"change",n=>{var i=n?s.defaultChecked:s.checked;e(i)}),Ns(t)==null&&e(s.checked),Vn(()=>{var n=t();s.checked=!!n})}function $n(s){var t=s.type;return t==="number"||t==="range"}function Yn(s){return s===""?null:+s}function Gn(s,t){return s===t||(s==null?void 0:s[Ka])===t}function sl(s={},t,e,n){var i=nt.r,l=Ae;return la(()=>{var c,u;return Vn(()=>{c=u,u=[],Ns(()=>{Gn(e(...u),s)||(t(s,...u),c&&Gn(e(...c),s)&&t(null,...c))})}),()=>{let d=l;for(;d!==i&&d.parent!==null&&d.parent.f&Qn;)d=d.parent;const p=()=>{u&&Gn(e(...u),s)&&t(null,...u)},_=d.teardown;d.teardown=()=>{p(),_==null||_()}}}),s}function qe(s,t,e,n){var $,F;var i=!Wa||(e&ml)!==0,l=(e&wl)!==0,c=(e&xl)!==0,u=n,d=!0,p=void 0,_=()=>c&&i?(p!=null||(p=Za(n)),a(p)):(d&&(d=!1,u=c?Ns(n):n),u);let h;if(l){var v=Ka in s||Dl in s;h=(F=($=wa(s,t))==null?void 0:$.set)!=null?F:v&&t in s?b=>s[t]=b:void 0}var x,y=!1;l?[x,y]=eo(()=>s[t]):x=s[t],x===void 0&&n!==void 0&&(x=_(),h&&(i&&Bl(),h(x)));var C;if(i?C=()=>{var b=s[t];return b===void 0?_():(d=!0,b)}:C=()=>{var b=s[t];return b!==void 0&&(u=void 0),b===void 0?u:b},i&&!(e&yl))return C;if(h){var k=s.$$legacy;return function(b,L){return arguments.length>0?((!i||!L||k||y)&&h(L?C():b),b):C()}}var S=!1,D=(e&bl?Za:ki)(()=>(S=!1,C()));l&&a(D);var V=Ae;return function(b,L){if(arguments.length>0){const H=L?a(D):i&&l?Be(b):b;return f(D,H),S=!0,u!==void 0&&(u=H),b}return Ds&&S||V.f&ns?D.v:a(D)}}const Zo="modulepreload",Xo=function(s){return"/"+s},Gi={},Qo=function(t,e,n){let i=Promise.resolve();if(e&&e.length>0){document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),u=(c==null?void 0:c.nonce)||(c==null?void 0:c.getAttribute("nonce"));i=Promise.allSettled(e.map(d=>{if(d=Xo(d),d in Gi)return;Gi[d]=!0;const p=d.endsWith(".css"),_=p?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${d}"]${_}`))return;const h=document.createElement("link");if(h.rel=p?"stylesheet":Zo,p||(h.as="script"),h.crossOrigin="",h.href=d,u&&h.setAttribute("nonce",u),document.head.appendChild(h),p)return new Promise((v,x)=>{h.addEventListener("load",v),h.addEventListener("error",()=>x(new Error(`Unable to preload CSS for ${d}`)))})}))}function l(c){const u=new Event("vite:preloadError",{cancelable:!0});if(u.payload=c,window.dispatchEvent(u),!u.defaultPrevented)throw c}return i.then(c=>{for(const u of c||[])u.status==="rejected"&&l(u.reason);return t().catch(l)})},ec="/assets/app_icon-CfHainhY.png";function tc(s,t,e,n){if(typeof t=="function"?s!==t||!n:!t.has(s))throw new TypeError("Cannot read private member from an object whose class did not declare it");return e==="m"?n:e==="a"?n.call(s):n?n.value:t.get(s)}function sc(s,t,e,n,i){if(typeof t=="function"?s!==t||!0:!t.has(s))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(s,e),e}var Sn;const ls="__TAURI_TO_IPC_KEY__";function ac(s,t=!1){return window.__TAURI_INTERNALS__.transformCallback(s,t)}async function O(s,t={},e){return window.__TAURI_INTERNALS__.invoke(s,t,e)}class nc{get rid(){return tc(this,Sn,"f")}constructor(t){Sn.set(this,void 0),sc(this,Sn,t)}async close(){return O("plugin:resources|close",{rid:this.rid})}}Sn=new WeakMap;var Ut;(function(s){s.WINDOW_RESIZED="tauri://resize",s.WINDOW_MOVED="tauri://move",s.WINDOW_CLOSE_REQUESTED="tauri://close-requested",s.WINDOW_DESTROYED="tauri://destroyed",s.WINDOW_FOCUS="tauri://focus",s.WINDOW_BLUR="tauri://blur",s.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",s.WINDOW_THEME_CHANGED="tauri://theme-changed",s.WINDOW_CREATED="tauri://window-created",s.WINDOW_SUSPENDED="tauri://suspended",s.WINDOW_RESUMED="tauri://resumed",s.WEBVIEW_CREATED="tauri://webview-created",s.DRAG_ENTER="tauri://drag-enter",s.DRAG_OVER="tauri://drag-over",s.DRAG_DROP="tauri://drag-drop",s.DRAG_LEAVE="tauri://drag-leave"})(Ut||(Ut={}));async function al(s,t){window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener(s,t),await O("plugin:event|unlisten",{event:s,eventId:t})}async function gt(s,t,e){var n;const i=typeof(e==null?void 0:e.target)=="string"?{kind:"AnyLabel",label:e.target}:(n=e==null?void 0:e.target)!==null&&n!==void 0?n:{kind:"Any"};return O("plugin:event|listen",{event:s,target:i,handler:ac(t)}).then(l=>async()=>al(s,l))}async function ic(s,t,e){return gt(s,n=>{al(s,n.id),t(n)},e)}async function rc(s,t){await O("plugin:event|emit",{event:s,payload:t})}async function lc(s,t,e){await O("plugin:event|emit_to",{target:typeof s=="string"?{kind:"AnyLabel",label:s}:s,event:t,payload:e})}const oc={engine:{backend:"auto",inference_mode:"Balanced",whisper_cpp:{model_dir:"",model_size:"tiny",device:"auto",threads:0},moonshine:{model_size:"base",language:"en"}},audio:{vad_threshold:.5,min_silence_duration_ms:500,input_device_index:null,evdev_device:null,noise_suppression:!1,gain:1,dynamic_stream:!0},ui:{show_overlay:!0,overlay_style:"mono_bars",overlay_position:"center",overlay_monitor:"primary",auto_show_settings:!0,show_notification:!1,history_enabled:!1},features:{remove_fillers:!0,custom_vocabulary:[],spoken_punctuation:!0,auto_format_lists:!0,quiet_mode:!1,snippets:{}},openai:{enabled:!1,model:"llama3.2:1b",mode:"clean",custom_prompt:null,system_prompt:"Fix grammar and punctuation only. Return only the corrected text, no commentary.",user_prompt:"{text}",endpoint:"http://localhost:11434",api_key:null,timeout_secs:8},tts:{enabled:!1,engine:"espeak",voice:"en-us-lessac-medium",voice_dir:"",stop_key:["KEY_ESCAPE"],response_overlay:!0,speed:1,gpu:!1,pocket_tts:{voice:"alba",prewarm:!1,hf_token:null,voice_dir:""}},mcp:{server_enabled:!1,record_timeout:15,visual_feedback:!0},atspi:{injection:!0,context_prompt:!0,auto_code_mode:!0}},$t=on(oc),Es=on(!1),fi=on(!1);let Qa=!1,Jn=null;async function cc(){try{const s=await O("get_config");$t.set(s),Es.set(!1),fi.set(!0),setTimeout(()=>{Qa=!0},0)}catch(s){console.error("loadConfig:",s),fi.set(!0),setTimeout(()=>{Qa=!0},0)}}async function nl(s){await O("save_config",{newConfig:s}),Es.set(!1)}$t.subscribe(s=>{Qa&&(Jn&&clearTimeout(Jn),Jn=setTimeout(async()=>{try{await nl(s),console.log("Config auto-saved successfully!")}catch(t){console.error("Auto-saving config failed:",t)}},400))});cc();gt("config-changed",s=>{Qa=!1,$t.set(s.payload),setTimeout(()=>{Qa=!0},0)}).catch(s=>{console.error("Failed to setup config-changed listener:",s)});const Et=on({recording:!1,processing:!1,speaking:!1,mcp_recording:!1,audio_ready:!0,word_count:0,active_target_id:"default",active_target_label:"Focused Window"}),uc=cn(Et,s=>s.recording),dc=cn(Et,s=>s.speaking),vc=cn(Et,s=>s.mcp_recording);cn(Et,s=>s.word_count);cn(Et,s=>{var t;return(t=s.active_target_label)!=null?t:"Focused Window"});gt("status-tick",s=>{Et.set(s.payload)});O("get_status").then(Et.set).catch(console.error);var pc=E('

General

History

When enabled, completed transcripts are saved to the History log. Disabled by default.

MCP Server

Socket: /tmp/voxctrl-mcp.sock (Linux) / \\\\.\\pipe\\voxctrl-mcp (Windows)

AT-SPI2 (Linux)

');function fc(s,t){$e(t,!0);let e=qe(t,"cfg",15);function n(){Es.set(!0)}var i=pc(),l=r(o(i),2),c=r(o(l),2),u=r(o(c),2),d=r(l,2),p=r(o(d),2),_=r(o(p),2),h=r(p,2),v=r(o(h),2),x=r(h,2),y=r(o(x),2),C=r(d,2),k=r(o(C),2),S=r(o(k),2),D=r(k,2),V=r(o(D),2),$=r(D,2),F=r(o($),2);K("change",u,n),Xe(u,()=>e().ui.history_enabled,b=>e(e().ui.history_enabled=b,!0)),K("change",_,n),Xe(_,()=>e().mcp.server_enabled,b=>e(e().mcp.server_enabled=b,!0)),K("change",v,n),Xe(v,()=>e().mcp.visual_feedback,b=>e(e().mcp.visual_feedback=b,!0)),K("change",y,n),ge(y,()=>e().mcp.record_timeout,b=>e(e().mcp.record_timeout=b,!0)),K("change",S,n),Xe(S,()=>e().atspi.injection,b=>e(e().atspi.injection=b,!0)),K("change",V,n),Xe(V,()=>e().atspi.context_prompt,b=>e(e().atspi.context_prompt=b,!0)),K("change",F,n),Xe(F,()=>e().atspi.auto_code_mode,b=>e(e().atspi.auto_code_mode=b,!0)),g(s,i),Ye()}Wt(["change"]);var hc=E(''),_c=E('
'),gc=E('
');function bt(s,t){$e(t,!0);let e=qe(t,"value",15),n=qe(t,"options",19,()=>[]),i=qe(t,"disabled",3,!1),l=B(!1),c=B(null),u=he(()=>n().map(C=>typeof C=="string"?{value:C,label:C,disabled:!1}:{value:C.value,label:C.label,disabled:!!C.disabled})),d=he(()=>{const C=a(u).find(k=>k.value===e());return C?C.label:e()!==void 0&&e()!==null?String(e()):""});ka(()=>{if(!a(l))return;const C=k=>{a(c)&&!a(c).contains(k.target)&&f(l,!1)};return document.addEventListener("click",C),()=>{document.removeEventListener("click",C)}});function p(C){e(C),f(l,!1),t.onchange&&t.onchange(C)}var _=gc(),h=o(_),v=o(h),x=r(h,2);{var y=C=>{var k=_c();ht(k,21,()=>a(u),ft,(S,D)=>{var V=hc();let $;var F=o(V);G(()=>{$=ye(V,1,"custom-dropdown-item svelte-1heock4",null,$,{selected:a(D).value===e()}),V.disabled=a(D).disabled,X(F,a(D).label)}),K("click",V,b=>{b.preventDefault(),b.stopPropagation(),p(a(D).value)}),g(S,V)}),g(C,k)};U(x,C=>{a(l)&&!i()&&C(y)})}sl(_,C=>f(c,C),()=>a(c)),G(()=>{h.disabled=i(),X(v,a(d))}),K("click",h,()=>f(l,!a(l))),g(s,_),Ye()}Wt(["click"]);var bc=E('
'),mc=E('

Visual & Feedback

Overlay & HUD

Alerts & OS Integration

Application Window

');function yc(s,t){$e(t,!0);let e=qe(t,"cfg",15),n=B(Be([])),i=B(Be([])),l=he(()=>[{value:"voice_card",label:"Voice Card"},{value:"waveform",label:"Waveform"},{value:"pulse",label:"Pulse Ring"},{value:"blue_wave",label:"Ocean Wave"},{value:"mono_bars",label:"Mono Bars"},{value:"spectrum",label:"Neon Spectrum"},{value:"terminal",label:"Retro Terminal"},{value:"vinyl",label:"Analog VU"},...a(n).map(w=>({value:w.name,label:w.name}))]);const c=[{value:"top",label:"Top of screen"},{value:"center",label:"Center of screen"},{value:"bottom",label:"Bottom of screen"}];let u=he(()=>[{value:"primary",label:"Primary Monitor"},...a(i).filter(w=>w.name).map(w=>({value:w.name,label:`${w.name} (${w.width}x${w.height})${w.is_primary?" [Primary]":""}`}))]);rt(async()=>{try{f(n,await O("get_custom_overlays"),!0)}catch(w){console.error("Failed to fetch custom overlays:",w)}try{f(i,await O("get_available_monitors"),!0)}catch(w){console.error("Failed to fetch available monitors:",w)}});function d(){Es.set(!0)}var p=mc(),_=r(o(p),2),h=r(o(_),2),v=r(o(h),2),x=r(h,2),y=r(o(x),2);bt(y,{get options(){return a(l)},onchange:d,get value(){return e().ui.overlay_style},set value(w){e(e().ui.overlay_style=w,!0)}});var C=r(x,2),k=r(o(C),2);bt(k,{get options(){return c},onchange:d,get value(){return e().ui.overlay_position},set value(w){e(e().ui.overlay_position=w,!0)}});var S=r(C,2),D=r(o(S),2);bt(D,{get options(){return a(u)},onchange:d,get value(){return e().ui.overlay_monitor},set value(w){e(e().ui.overlay_monitor=w,!0)}});var V=r(S,2);{var $=w=>{var J=bc(),q=o(J),N=o(q);G(()=>{var M;return X(N,`⚠️ Configured monitor "${(M=e().ui.overlay_monitor)!=null?M:""}" is disconnected. Using Primary Monitor.`)}),g(w,J)},F=he(()=>e().ui.overlay_monitor!=="primary"&&a(i).length>0&&!a(i).some(w=>w.name===e().ui.overlay_monitor));U(V,w=>{a(F)&&w($)})}var b=r(_,2),L=r(o(b),2),H=r(o(L),2),se=r(b,2),oe=r(o(se),2),ue=r(o(oe),2);K("change",v,d),Xe(v,()=>e().ui.show_overlay,w=>e(e().ui.show_overlay=w,!0)),K("change",H,d),Xe(H,()=>e().ui.show_notification,w=>e(e().ui.show_notification=w,!0)),K("change",ue,d),Xe(ue,()=>e().ui.auto_show_settings,w=>e(e().ui.auto_show_settings=w,!0)),g(s,p),Ye()}Wt(["change"]);var wc=E(`
⚠️
Voice Model Not Downloaded

The configuration specifies a voice model ( ) that is not currently downloaded. Please select the model size to - use and download it below, or choose another model.

`),xc=E('⏳ Checking local model files...'),kc=E(' '),Tc=E('✔ Model downloaded and ready'),Ec=E('
❌ Model file missing
'),Sc=E('

'),Ac=E('

Whisper.cpp Settings

Model directory (leave blank for default)

Default model directory: ~/.local/share/voxctrl/models/

'),Cc=E('

Moonshine Settings

'),Pc=E('

Inference Engine

Backend

');function Mc(s,t){$e(t,!0);let e=qe(t,"cfg",15);function n(){Es.set(!0)}const i=["tiny","tiny.en","base","base.en","small","small.en","medium","medium.en","large-v2","large-v3","large-v3-turbo"],l=[{value:"auto",label:"Auto-detect"},{value:"whisper-cpp",label:"Whisper.cpp"},{value:"moonshine",label:"Moonshine (CPU only)"}],c=[{value:"Balanced",label:"Balanced"},{value:"Aggressive",label:"Aggressive (shorter silence)"}];let u=he(()=>i.map(M=>({value:M,label:`${M}${a(h)[M]?" ✔":""}`}))),d=B(!1),p=he(()=>[{value:"auto",label:"Auto"},...a(d)?[{value:"cuda",label:"CUDA (NVIDIA)"}]:[],{value:"vulkan",label:"Vulkan (AMD/Intel)"},{value:"cpu",label:"CPU"}]);const _=[{value:"base",label:"Base"},{value:"tiny",label:"Tiny"}];let h=B(Be({})),v=B(!1),x=B(!1),y=B(null);async function C(){f(v,!0);const M={};for(const j of i)try{M[j]=await O("check_model_downloaded",{modelSize:j,modelDir:e().engine.whisper_cpp.model_dir})}catch(z){console.error("Failed to check download status for model "+j,z),M[j]=!1}f(h,M,!0),f(v,!1)}async function k(M){if(!a(x)){f(x,!0);try{await O("download_model",{modelSize:M,modelDir:e().engine.whisper_cpp.model_dir}),a(h)[M]=!0}catch(j){alert(`Failed to download model: ${j}`)}finally{f(x,!1)}}}async function S(){n();const M=e().engine.whisper_cpp.model_size;a(h)[M]||await k(M)}async function D(){const M=e().engine.whisper_cpp.model_dir;if(!M){f(y,null);return}const j=await O("check_directory_exists",{path:M});f(y,j?null:"This folder does not exist. Please create it first or leave blank for the default location.",!0),a(y)||await C()}function V(){n()}function $(M){M.key==="Enter"&&M.currentTarget.blur()}rt(async()=>{C(),f(d,await O("cuda_enabled"),!0),!a(d)&&e().engine.whisper_cpp.device==="cuda"&&(e(e().engine.whisper_cpp.device="auto",!0),n())});var F=Pc(),b=r(o(F),2);{var L=M=>{var j=wc(),z=r(o(j),2),I=r(o(z),2),Q=r(o(I)),ce=o(Q);G(()=>X(ce,e().engine.whisper_cpp.model_size)),g(M,j)};U(b,M=>{e().engine.backend!=="moonshine"&&!a(v)&&!a(h)[e().engine.whisper_cpp.model_size]&&M(L)})}var H=r(b,2),se=r(o(H),2),oe=r(o(se),2);bt(oe,{get options(){return l},onchange:n,get value(){return e().engine.backend},set value(M){e(e().engine.backend=M,!0)}});var ue=r(se,2),w=r(o(ue),2);bt(w,{get options(){return c},onchange:n,get value(){return e().engine.inference_mode},set value(M){e(e().engine.inference_mode=M,!0)}});var J=r(H,2);{var q=M=>{var j=Ac(),z=r(o(j),2),I=r(o(z),2);bt(I,{get options(){return a(u)},onchange:S,get value(){return e().engine.whisper_cpp.model_size},set value(A){e(e().engine.whisper_cpp.model_size=A,!0)}});var Q=r(z,2),ce=o(Q);{var ie=A=>{var T=xc();g(A,T)},W=A=>{var T=kc(),Z=o(T);G(()=>{var Se;return X(Z,`⏳ Downloading ${(Se=e().engine.whisper_cpp.model_size)!=null?Se:""} (GGUF format)...`)}),g(A,T)},ee=A=>{var T=Tc();g(A,T)},ae=A=>{var T=Ec(),Z=r(o(T),2);K("click",Z,()=>k(e().engine.whisper_cpp.model_size)),g(A,T)};U(ce,A=>{a(v)?A(ie):a(x)?A(W,1):a(h)[e().engine.whisper_cpp.model_size]?A(ee,2):A(ae,-1)})}var ve=r(Q,2),re=r(o(ve),2);bt(re,{get options(){return a(p)},onchange:n,get value(){return e().engine.whisper_cpp.device},set value(A){e(e().engine.whisper_cpp.device=A,!0)}});var ne=r(ve,2),pe=r(o(ne),2);let Ie;var P=r(pe,2);{var Y=A=>{var T=Sc(),Z=o(T);G(()=>X(Z,a(y))),g(A,T)};U(P,A=>{a(y)&&A(Y)})}var te=r(ne,2),de=r(o(te),2);G(()=>Ie=ye(pe,1,"svelte-nfi4ak",null,Ie,{"field-input-error":!!a(y)})),K("change",pe,V),Ms("blur",pe,D),K("keydown",pe,$),ge(pe,()=>e().engine.whisper_cpp.model_dir,A=>e(e().engine.whisper_cpp.model_dir=A,!0)),K("change",de,n),ge(de,()=>e().engine.whisper_cpp.threads,A=>e(e().engine.whisper_cpp.threads=A,!0)),g(M,j)},N=M=>{var j=Cc(),z=r(o(j),2),I=r(o(z),2);bt(I,{get options(){return _},onchange:n,get value(){return e().engine.moonshine.model_size},set value(ie){e(e().engine.moonshine.model_size=ie,!0)}});var Q=r(z,2),ce=r(o(Q),2);K("change",ce,n),ge(ce,()=>e().engine.moonshine.language,ie=>e(e().engine.moonshine.language=ie,!0)),g(M,j)};U(J,M=>{e().engine.backend!=="moonshine"?M(q):M(N,-1)})}g(s,F),Ye()}Wt(["click","change","keydown"]);var Oc=E("
"),Ic=E('
'),Dc=E('

Audio

Input Device

Microphone Monitor

Only opens the microphone stream when recording is triggered. If your first words are being clipped due to hardware delay, disable this feature to keep the stream always open.

Voice Activity Detection

Processing

');function Lc(s,t){$e(t,!0);let e=qe(t,"cfg",15);function n(){Es.set(!0)}let i=B(Be([])),l=he(()=>[{value:-1,label:"Default system device"},...a(i).map(ne=>({value:ne.index,label:ne.name}))]),c=B(0),u=B(0),d=B(0),p=0,_=B(null),h;function v(){const ne=a(c);ne>a(u)?f(u,a(u)+(ne-a(u))*.45):f(u,a(u)+(ne-a(u))*.12),a(u)>a(d)?(f(d,a(u),!0),p=25):p>0?p--:f(d,Math.max(0,a(d)-.012),!0),h=requestAnimationFrame(v)}rt(async()=>{f(i,await O("list_audio_devices"),!0);try{await O("start_monitoring_audio"),f(_,await gt("audio-level",ne=>{f(c,ne.payload,!0)}),!0)}catch(ne){console.error("Failed to start audio monitoring:",ne)}h=requestAnimationFrame(v)}),Qr(async()=>{h&&cancelAnimationFrame(h),a(_)&&a(_)();try{await O("stop_monitoring_audio")}catch(ne){console.error("Failed to stop audio monitoring:",ne)}});var x=Dc(),y=r(o(x),2),C=r(o(y),2),k=r(o(C),2);{let ne=he(()=>{var pe;return(pe=e().audio.input_device_index)!=null?pe:-1});bt(k,{get value(){return a(ne)},get options(){return a(l)},onchange:pe=>{e(e().audio.input_device_index=pe<0?null:pe,!0),n()}})}var S=r(C,2),D=o(S),V=r(o(D),2);let $;var F=r(V,2),b=o(F),L=r(D,2),H=o(L),se=o(H);ht(se,16,()=>Array(24),ft,(ne,pe,Ie)=>{const P=he(()=>Ie/24),Y=he(()=>a(u)>=a(P)),te=he(()=>Ie>=17);var de=Oc();let A;G(()=>A=ye(de,1,"vu-segment svelte-1msnq7i",null,A,{active:a(Y),orange:a(te)})),g(ne,de)});var oe=r(se,2);{var ue=ne=>{var pe=Ic();G(Ie=>$s(pe,`left: ${Ie!=null?Ie:""}%;`),[()=>Math.min(.99,a(d))*100]),g(ne,pe)};U(oe,ne=>{a(d)>.01&&ne(ue)})}var w=r(S,2),J=r(o(w),2),q=r(y,2),N=r(o(q),2),M=r(o(N),2),j=r(M,2),z=o(j),I=r(N,2),Q=r(o(I),2),ce=r(q,2),ie=r(o(ce),2),W=r(o(ie),2),ee=r(ie,2),ae=r(o(ee),2),ve=r(ae,2),re=o(ve);G((ne,pe)=>{$=ye(V,1,"vu-status-dot svelte-1msnq7i",null,$,{active:a(c)>.005}),X(b,a(c)>.005?"Signal Detected":"Listening..."),X(z,ne),X(re,`${pe!=null?pe:""}×`)},[()=>e().audio.vad_threshold.toFixed(2),()=>e().audio.gain.toFixed(1)]),K("change",J,n),Xe(J,()=>e().audio.dynamic_stream,ne=>e(e().audio.dynamic_stream=ne,!0)),K("change",M,n),ge(M,()=>e().audio.vad_threshold,ne=>e(e().audio.vad_threshold=ne,!0)),K("change",Q,n),ge(Q,()=>e().audio.min_silence_duration_ms,ne=>e(e().audio.min_silence_duration_ms=ne,!0)),K("change",W,n),Xe(W,()=>e().audio.noise_suppression,ne=>e(e().audio.noise_suppression=ne,!0)),K("change",ae,n),ge(ae,()=>e().audio.gain,ne=>e(e().audio.gain=ne,!0)),g(s,x),Ye()}Wt(["change"]);var Nc=E(''),Rc=E(' '),Fc=E('
Shell Executor Settings
Terminal Command Shell command

Use inside the command string as a placeholder to substitute transcribed speech.

'),Wc=E('
Local File Writer Settings
'),zc=E('
Network Socket settings
'),qc=E('
FIFO Named Pipe settings
'),Vc=E('
Linux DBus emitter settings
'),Bc=E(''),Uc=E(''),jc=E(' '),Hc=E('
Method
Custom Post Body JSON Template

Must be valid JSON. Use to substitute transcribed speech.

',1),Kc=E(' '),$c=E('
Webhook Secret Token (HMAC)
Custom Webhook Body JSON Template

Must be valid JSON. Use to substitute transcribed speech.

',1),Yc=E('
API Endpoint Client settings
REST endpoint URL
'),Gc=E(' '),Jc=E('
MCP Server Client settings
Custom Socket/Pipe Path Optional override

Leave empty to use defaults (/tmp/voxctrl-mcp.sock on Linux, \\\\.\\pipe\\voxctrl-mcp on Windows).

MCP Tool Name
Custom Tool Arguments JSON Template

Must be valid JSON. Use to substitute transcribed speech.

'),Zc=E(''),Xc=E(''),Qc=E('
');function il(s,t){$e(t,!0);let e=qe(t,"editingTarget",15),n=qe(t,"isNested",3,!1),i=B(!0),l=B(""),c=B(""),u=B(""),d=he(()=>!e()||e().delivery!=="exec"||(e().command||"").includes("{text}")?null:"Command must contain '{text}' placeholder."),p=he(()=>{if(!a(l).trim())return null;try{JSON.parse(a(l))}catch(S){return"Invalid JSON format: "+S.message}return a(l).includes("{text}")?null:"Arguments must contain '{text}' placeholder."}),_=he(()=>{if(!a(c).trim())return null;try{JSON.parse(a(c))}catch(S){return"Invalid JSON format: "+S.message}return a(c).includes("{text}")?null:"JSON template must contain '{text}' placeholder."}),h=he(()=>{if(!a(u).trim())return null;try{JSON.parse(a(u))}catch(S){return"Invalid JSON format: "+S.message}return a(u).includes("{text}")?null:"JSON template must contain '{text}' placeholder."});function v(S){function D(){S.style.height="auto",S.style.height=`${S.scrollHeight}px`}S.addEventListener("input",D);const V=setTimeout(D,0);return{update(){D()},destroy(){clearTimeout(V),S.removeEventListener("input",D)}}}rt(()=>{e()&&(e().processing||e(e().processing={},!0),e().file_mode||e(e().file_mode="append",!0),f(i,e().processing.apply_snippets!==!1),f(l,e().mcp_args?JSON.stringify(e().mcp_args,null,2):`{ - "text": "{text}" -}`,!0),f(c,e().http_json_template?JSON.stringify(e().http_json_template,null,2):`{ - "text": "{text}" -}`,!0),f(u,e().webhook_json_template?JSON.stringify(e().webhook_json_template,null,2):`{ - "text": "{text}" -}`,!0))});function x(){if(e()){if(e().id.trim()===""){alert("Target ID cannot be empty.");return}if(e().delivery==="exec"&&a(d)){alert("Validation Error: "+a(d));return}if(e().delivery==="mcp"){if(a(p)){alert("Validation Error: "+a(p));return}try{e(e().mcp_args=JSON.parse(a(l)),!0)}catch{alert("Invalid JSON format in MCP Custom Tool Arguments.");return}}if(e().delivery==="http"){if(a(_)){alert("Validation Error: "+a(_));return}try{e(e().http_json_template=JSON.parse(a(c)),!0)}catch{alert("Invalid JSON format in HTTP Custom Post Body.");return}}if(e().delivery==="webhook"){if(a(h)){alert("Validation Error: "+a(h));return}try{e(e().webhook_json_template=JSON.parse(a(u)),!0)}catch{alert("Invalid JSON format in Webhook Custom Post Body.");return}}e(e().processing={apply_snippets:a(i)},!0),t.onSave()}}var y=Xr(),C=Ct(y);{var k=S=>{var D=Qc(),V=o(D),$=o(V),F=o($),b=o(F),L=r(F,2),H=r($,2),se=o(H);{var oe=le=>{var me=Nc(),Oe=r(o(me),2);G(()=>Oe.disabled=!t.isNew),ge(Oe,()=>e().id,Ve=>e(e().id=Ve,!0)),g(le,me)};U(se,le=>{n()||le(oe)})}var ue=r(se,2),w=r(o(ue),2),J=r(ue,2),q=r(o(J),2);bt(q,{options:[{value:"inject",label:"Inject Text Directly (Simulate keyboard)"},{value:"clipboard",label:"Save to Clipboard"},{value:"exec",label:"Execute Command"},{value:"file",label:"Write to File"},{value:"pipe",label:"FIFO Named Pipe"},{value:"socket",label:"TCP / Unix Socket"},{value:"dbus",label:"DBus Signal"},{value:"http",label:"HTTP Custom Client"},{value:"webhook",label:"Send Webhook Event"},{value:"mcp",label:"Call MCP Server Tool"},{value:"speak",label:"Speak Text Aloud (TTS)"}],get value(){return e().delivery},set value(le){e(e().delivery=le,!0)}});var N=r(J,2);{var M=le=>{var me=Fc(),Oe=r(o(me),2),Ve=r(o(Oe),2);_t(Ve,"placeholder","e.g. xdg-open {text}");var Ge=r(Ve,2),dt=r(o(Ge));dt.textContent="{text}";var Qe=r(Ge,2);{var Ze=Ue=>{var je=Rc(),We=o(je);G(()=>{var lt;return X(We,`⚠️ ${(lt=a(d))!=null?lt:""}`)}),g(Ue,je)};U(Qe,Ue=>{a(d)&&Ue(Ze)})}G(()=>ye(Ve,1,`full-width-input ${a(d)?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":""}`,"svelte-oc07pw")),ge(Ve,()=>e().command,Ue=>e(e().command=Ue,!0)),g(le,me)};U(N,le=>{e().delivery==="exec"&&le(M)})}var j=r(N,2);{var z=le=>{var me=Wc(),Oe=r(o(me),2),Ve=r(o(Oe),2),Ge=r(Oe,2),dt=r(o(Ge),2);bt(dt,{options:[{value:"append",label:"Append (Add to end of file)"},{value:"prepend",label:"Prepend (Add to beginning of file)"}],get value(){return e().file_mode},set value(We){e(e().file_mode=We,!0)}});var Qe=r(Ge,2),Ze=r(o(Qe),2),Ue=r(Qe,2),je=o(Ue);ge(Ve,()=>e().file_path,We=>e(e().file_path=We,!0)),ge(Ze,()=>e().file_prefix,We=>e(e().file_prefix=We,!0)),Xe(je,()=>e().file_timestamp,We=>e(e().file_timestamp=We,!0)),g(le,me)};U(j,le=>{e().delivery==="file"&&le(z)})}var I=r(j,2);{var Q=le=>{var me=zc(),Oe=r(o(me),2),Ve=r(o(Oe),2),Ge=r(Oe,2),dt=r(o(Ge),2),Qe=r(Ge,2),Ze=r(o(Qe),2);ge(Ve,()=>e().socket_host,Ue=>e(e().socket_host=Ue,!0)),ge(dt,()=>e().socket_port,Ue=>e(e().socket_port=Ue,!0)),ge(Ze,()=>e().socket_unix,Ue=>e(e().socket_unix=Ue,!0)),g(le,me)};U(I,le=>{e().delivery==="socket"&&le(Q)})}var ce=r(I,2);{var ie=le=>{var me=qc(),Oe=r(o(me),2),Ve=r(o(Oe),2),Ge=r(Oe,2),dt=r(o(Ge),2);ge(Ve,()=>e().pipe_path,Qe=>e(e().pipe_path=Qe,!0)),ge(dt,()=>e().response_pipe,Qe=>e(e().response_pipe=Qe,!0)),g(le,me)};U(ce,le=>{e().delivery==="pipe"&&le(ie)})}var W=r(ce,2);{var ee=le=>{var me=Vc(),Oe=r(o(me),2),Ve=r(o(Oe),2);ge(Ve,()=>e().dbus_signal,Ge=>e(e().dbus_signal=Ge,!0)),g(le,me)};U(W,le=>{e().delivery==="dbus"&&le(ee)})}var ae=r(W,2);{var ve=le=>{var me=Yc(),Oe=r(o(me),2),Ve=r(o(Oe),2);{var Ge=je=>{var We=Bc();ge(We,()=>e().http_url,lt=>e(e().http_url=lt,!0)),g(je,We)},dt=je=>{var We=Uc();ge(We,()=>e().webhook_url,lt=>e(e().webhook_url=lt,!0)),g(je,We)};U(Ve,je=>{e().delivery==="http"?je(Ge):je(dt,-1)})}var Qe=r(Oe,2);{var Ze=je=>{var We=Hc(),lt=Ct(We),et=r(o(lt),2);bt(et,{options:[{value:"POST",label:"POST"},{value:"GET",label:"GET"},{value:"PUT",label:"PUT"}],get value(){return e().http_method},set value(He){e(e().http_method=He,!0)}});var Dt=r(lt,2),ot=r(o(Dt),2);_t(ot,"placeholder",'{"text": "{text}"}'),la(()=>ge(ot,()=>a(c),He=>f(c,He))),ua(ot,He=>v==null?void 0:v(He));var St=r(ot,2),Yt=r(o(St));Yt.textContent="{text}";var Ss=r(St,2);{var yt=He=>{var os=jc(),Pt=o(os);G(()=>{var De;return X(Pt,`⚠️ ${(De=a(_))!=null?De:""}`)}),g(He,os)};U(Ss,He=>{a(_)&&He(yt)})}G(()=>ye(ot,1,ps(a(_)?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":""),"svelte-oc07pw")),g(je,We)},Ue=je=>{var We=$c(),lt=Ct(We),et=r(o(lt),2),Dt=r(lt,2),ot=r(o(Dt),2);_t(ot,"placeholder",'{"text": "{text}"}'),la(()=>ge(ot,()=>a(u),He=>f(u,He))),ua(ot,He=>v==null?void 0:v(He));var St=r(ot,2),Yt=r(o(St));Yt.textContent="{text}";var Ss=r(St,2);{var yt=He=>{var os=Kc(),Pt=o(os);G(()=>{var De;return X(Pt,`⚠️ ${(De=a(h))!=null?De:""}`)}),g(He,os)};U(Ss,He=>{a(h)&&He(yt)})}G(()=>ye(ot,1,ps(a(h)?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":""),"svelte-oc07pw")),ge(et,()=>e().webhook_secret,He=>e(e().webhook_secret=He,!0)),g(je,We)};U(Qe,je=>{e().delivery==="http"?je(Ze):je(Ue,-1)})}g(le,me)};U(ae,le=>{(e().delivery==="http"||e().delivery==="webhook")&&le(ve)})}var re=r(ae,2);{var ne=le=>{var me=Jc(),Oe=r(o(me),2),Ve=r(o(Oe),2),Ge=r(Oe,2),dt=r(o(Ge),2),Qe=r(Ge,2),Ze=r(o(Qe),2);_t(Ze,"placeholder",'{"text": "{text}"}'),la(()=>ge(Ze,()=>a(l),et=>f(l,et))),ua(Ze,et=>v==null?void 0:v(et));var Ue=r(Ze,2),je=r(o(Ue));je.textContent="{text}";var We=r(Ue,2);{var lt=et=>{var Dt=Gc(),ot=o(Dt);G(()=>{var St;return X(ot,`⚠️ ${(St=a(p))!=null?St:""}`)}),g(et,Dt)};U(We,et=>{a(p)&&et(lt)})}G(()=>ye(Ze,1,ps(a(p)?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":""),"svelte-oc07pw")),ge(Ve,()=>e().mcp_path,et=>e(e().mcp_path=et,!0)),ge(dt,()=>e().mcp_tool,et=>e(e().mcp_tool=et,!0)),g(le,me)};U(re,le=>{e().delivery==="mcp"&&le(ne)})}var pe=r(re,2),Ie=r(o(pe),2),P=o(Ie),Y=r(Ie,2),te=o(Y),de=r(Y,2);{var A=le=>{var me=Zc(),Oe=o(me);Xe(Oe,()=>e().strip_newlines,Ve=>e(e().strip_newlines=Ve,!0)),g(le,me)};U(de,le=>{e().delivery==="inject"&&le(A)})}var T=r(de,2);{var Z=le=>{var me=Xc(),Oe=o(me);Xe(Oe,()=>a(i),Ve=>f(i,Ve)),g(le,me)};U(T,le=>{e().processing&&le(Z)})}var Se=r(T,2),ut=r(o(Se),2),zt=r(H,2),qt=o(zt),_s=r(qt,2);G(()=>{ye(D,1,`modal-backdrop ${n()?"target-modal-backdrop":""}`,"svelte-oc07pw"),X(b,t.isNew?"Create Target":"Edit Target")}),K("click",L,function(...le){var me;(me=t.onCancel)==null||me.apply(this,le)}),ge(w,()=>e().label,le=>e(e().label=le,!0)),Xe(P,()=>e().append_newline,le=>e(e().append_newline=le,!0)),Xe(te,()=>e().send_on_release,le=>e(e().send_on_release=le,!0)),ge(ut,()=>e().initial_prompt,le=>e(e().initial_prompt=le,!0)),K("click",qt,function(...le){var me;(me=t.onCancel)==null||me.apply(this,le)}),K("click",_s,x),g(S,D)};U(C,S=>{e()&&S(k)})}g(s,y),Ye()}Wt(["click"]);var eu=E('
⚠️ Conflict detected: Some key bindings share the same key combination and gesture type. Disabling one of the conflicting binds will fix the problem.
'),tu=E('CONFLICT'),su=E('LLM'),au=E(' '),nu=E(' ',1),iu=E('Delete? ',1),ru=E(''),lu=E('
'),ou=E('

No keyboard bindings defined. Create a binding to link a physical hotkey to a routing target!

'),cu=E(''),uu=E('
',1),du=E(''),vu=E('
'),pu=E(``),fu=E(''),hu=E('
'),_u=E(' '),gu=E('
(Click / Tab here to record)',1),bu=E(''),mu=E('
Press the trigger key now...
'),yu=E(' (Click / Tab here to change trigger key)',1),wu=E(''),xu=E('
Subkey Trigger (Pressed Key)
'),ku=E('⚠️ Warning: This key combination and gesture type conflicts with another existing binding.'),Tu=E('⚠️ Validation Error: Prompt template MUST contain the placeholder.'),Eu=E('

Prompt template MUST contain the placeholder. Leave empty to inherit the default user prompt.

'),Su=E('
System Prompt Override LLM Prompt

Overrides the default system prompt configured in Settings → OpenAI API. Leave empty to inherit it.

User Prompt Template LLM Prompt
'),Au=E(''),Cu=E('

Hotkey Bindings

Bind physical keyboard combinations to your output targets. Each hotkey supports customizable triggers (double-taps, holding keys, etc.)

',1);function Pu(s,t){$e(t,!0);let e=B(Be([])),n=B(Be([])),i=B(null),l=B(!1),c=B(null),u=B(null),d=B(null),p=B(!1),_=B(null),h=B(null),v=B(!1),x=B(""),y=B("custom"),C=B(""),k=B("");function S(A,T,Z){const Se=[...A].sort().join(","),ut=T==="chord"&&Z?`+${Z}`:"";return`${T}:${Se}${ut}`}let D=he(()=>{const A=new Map;for(const Z of a(n))if(Z.keys&&Z.keys.length>0){const Se=S(Z.keys,Z.gesture,Z.subkey);A.set(Se,(A.get(Se)||0)+1)}const T=new Set;for(const[Z,Se]of A.entries())Se>1&&T.add(Z);return T}),V=he(()=>{const A=new Map;for(const Z of a(n))if(!Z.disabled&&Z.keys&&Z.keys.length>0){const Se=S(Z.keys,Z.gesture,Z.subkey);A.set(Se,(A.get(Se)||0)+1)}const T=new Set;for(const[Z,Se]of A.entries())Se>1&&T.add(Z);return T}),$=he(()=>{if(!a(i)||!a(i).keys||a(i).keys.length===0)return!1;const A=S(a(i).keys,a(i).gesture,a(i).subkey);return a(n).some(T=>T.id!==a(i).id&&S(T.keys,T.gesture,T.subkey)===A)});function F(A){function T(){A.style.height="auto",A.style.height=`${A.scrollHeight}px`}A.addEventListener("input",T);const Z=setTimeout(T,0);return{update(){T()},destroy(){clearTimeout(Z),A.removeEventListener("input",T)}}}rt(async()=>{f(e,await O("get_targets"),!0),f(n,await O("get_bindings"),!0)});async function b(){try{await O("save_targets",{targets:a(e)}),console.log("Targets auto-saved successfully!")}catch(A){console.error("Failed to save targets:",A)}}async function L(){try{await O("save_bindings",{bindings:a(n)}),console.log("Bindings auto-saved successfully!")}catch(A){console.error("Failed to save bindings:",A)}}function H(A){return(A.target_ids&&A.target_ids.length>0?A.target_ids:[A.target_id]).map(Z=>{const Se=a(e).find(ut=>ut.id===Z);return Se?Se.label:Z==="default"?"Focused Window":Z}).join(", ")}function se(A){const T=a(e).find(Z=>Z.id===A);return T?`${T.label} (${T.delivery})`:A==="default"?"Focused Window":A}function oe(){if(a(e).length===0){alert("Please create at least one Output Target before making a hotkey binding.");return}f(l,!0),f(v,!1),f(x,""),f(y,"custom"),f(C,""),f(k,""),f(i,{id:"binding_"+Math.random().toString(36).substring(2,6),label:"New Binding",keys:["KEY_LEFTMETA","KEY_SPACE"],gesture:"hold",target_id:a(e)[0].id,target_ids:[a(e)[0].id],tap_ms:300,hold_threshold_ms:1e3,subkey:"",disabled:!1,openai_enabled:!1,openai_model:"",openai_mode:"custom",openai_prompt:"",openai_system_prompt:""},!0)}function ue(A){f(l,!1);const T=JSON.parse(JSON.stringify(A));T.target_ids||(T.target_ids=T.target_id?[T.target_id]:[]),f(v,T.openai_enabled===!0),f(x,T.openai_model||"",!0),f(y,T.openai_mode||"custom",!0),f(C,T.openai_prompt||"",!0),f(k,T.openai_system_prompt||"",!0),f(i,T,!0)}async function w(A){f(n,a(n).map(T=>T.id===A?{...T,disabled:!T.disabled}:T),!0),await L()}function J(){if(!a(i))return;a(i).target_ids||(a(i).target_ids=[a(i).target_id]);const A=a(e).find(Z=>!a(i).target_ids.includes(Z.id)),T=A?A.id:a(e)[0].id;a(i).target_ids=[...a(i).target_ids,T]}function q(A){!a(i)||!a(i).target_ids||(a(i).target_ids=a(i).target_ids.filter((T,Z)=>Z!==A))}async function N(){if(a(i)){if(a(i).id.trim()===""){alert("Binding ID cannot be empty.");return}if(a(i).keys.length===0){alert("Please capture at least one hotkey before saving.");return}if(a(i).gesture==="chord"&&(!a(i).subkey||a(i).subkey.trim()==="")){alert("Please capture a subkey trigger for the chord combo before saving.");return}if(a(v)&&a(y)==="custom"&&!a(C).includes("{text}")){alert(`LLM Configuration Error: -Your custom prompt template MUST contain the '{text}' placeholder so the model knows where to insert the transcribed text. - -Example: -write a haiku about {text}`);return}if(a(i).openai_enabled=a(v),a(i).openai_model=a(x),a(i).openai_mode=a(y),a(i).openai_prompt=a(C),a(i).openai_system_prompt=a(k),a(i).target_ids&&a(i).target_ids.length>0){if(a(i).target_ids=a(i).target_ids.filter(T=>T.trim()!==""),a(i).target_ids.length===0){alert("Please assign at least one Output Target.");return}if(new Set(a(i).target_ids).size!==a(i).target_ids.length){alert(`Duplicate targets detected. -You cannot assign the same Output Target multiple times to a single keybind.`);return}a(i).target_id=a(i).target_ids[0]}else a(i).target_id="",a(i).target_ids=[];if(a(l)){if(a(n).some(A=>A.id===a(i).id)){alert("Binding with this ID already exists.");return}f(n,[...a(n),a(i)],!0)}else f(n,a(n).map(A=>A.id===a(i).id?a(i):A),!0);f(i,null),f(c,null),await L()}}async function M(A){f(n,a(n).filter(T=>T.id!==A),!0),await L()}function j(A,T){const Z=T.toUpperCase();return A==="Control"?"KEY_LEFTCTRL":A==="Alt"?"KEY_LEFTALT":A==="Shift"?"KEY_LEFTSHIFT":A==="Meta"||A==="OS"||A==="Super"?"KEY_LEFTMETA":Z==="SPACE"?"KEY_SPACE":Z==="ENTER"?"KEY_ENTER":Z==="ESCAPE"||Z==="ESC"?"KEY_ESC":Z==="TAB"?"KEY_TAB":Z==="BACKSPACE"?"KEY_BACKSPACE":Z==="DELETE"?"KEY_DELETE":/^KEY[A-Z]$/.test(Z)?`KEY_${Z.slice(3)}`:Z.startsWith("KEY")?Z:Z.startsWith("DIGIT")?`KEY_${Z.replace("DIGIT","")}`:Z.startsWith("ARROW")?`KEY_${Z.replace("ARROW","")}`:Z.startsWith("F")&&Z.length>1?`KEY_${Z}`:A.length===1?`KEY_${A.toUpperCase()}`:`KEY_${Z}`}let z=B(Be([]));function I(A){if(!a(c)||!a(i))return;A.preventDefault(),A.stopPropagation();const T=j(A.key,A.code);a(c)==="keys"?(a(z).includes(T)||f(z,[...a(z),T],!0),A.key==="Escape"&&(a(i).keys=[...a(z)],f(z,[],!0),f(c,null))):a(c)==="subkey"&&(a(i).subkey=T,f(c,null))}function Q(A){!a(c)||!a(i)||(A.preventDefault(),A.stopPropagation(),a(c)==="keys"&&(a(z).length>0&&(a(i).keys=[...a(z)]),f(z,[],!0),f(c,null)))}function ce(){a(c)&&(a(c)==="keys"&&a(z).length>0&&a(i)&&(a(i).keys=[...a(z)],f(z,[],!0)),f(c,null))}function ie(A){f(_,A,!0),f(p,!0),f(d,{id:"new_target_"+Math.random().toString(36).substring(2,6),label:"New Target",delivery:"inject",file_prefix:"- ",file_timestamp:!0,file_mode:"append",http_method:"POST",http_json_template:{text:"{text}"},webhook_json_template:{text:"{text}"},mcp_tool:"speak_text",mcp_args:{text:"{text}"},send_on_release:!1,append_newline:!0,strip_newlines:!1,processing:{apply_snippets:!0}},!0)}function W(){f(d,null),f(_,null)}async function ee(){if(a(d)){if(a(e).some(A=>A.id===a(d).id)){alert("Target with this ID already exists.");return}f(e,[...a(e),a(d)],!0),a(_)!==null&&a(i)&&(a(i).target_ids||(a(i).target_ids=[]),a(i).target_ids[a(_)]=a(d).id),f(d,null),f(_,null),await b()}}var ae=Cu(),ve=Ct(ae),re=r(o(ve),2),ne=r(re,2);{var pe=A=>{var T=eu();g(A,T)};U(ne,A=>{a(D).size>0&&A(pe)})}var Ie=r(ne,2);ht(Ie,21,()=>a(n),ft,(A,T)=>{var Z=lu();let Se;var ut=o(Z);{var zt=De=>{var ct=tu();g(De,ct)},qt=he(()=>!a(T).disabled&&a(T).keys&&a(T).keys.length>0&&a(V).has(S(a(T).keys,a(T).gesture,a(T).subkey)));U(ut,De=>{a(qt)&&De(zt)})}var _s=r(ut,2),le=o(_s),me=o(le);let Oe;var Ve=o(me),Ge=r(me,2);{var dt=De=>{var ct=su();g(De,ct)};U(Ge,De=>{a(T).openai_enabled&&De(dt)})}var Qe=r(le,2),Ze=o(Qe),Ue=o(Ze);ht(Ue,17,()=>a(T).keys,ft,(De,ct)=>{var Vt=au(),R=o(Vt);G(_e=>X(R,_e),[()=>a(ct).replace("KEY_","")]),g(De,Vt)});var je=r(Ue,2);{var We=De=>{var ct=nu(),Vt=r(Ct(ct),2),R=o(Vt);G(_e=>X(R,_e),[()=>a(T).subkey.replace("KEY_","")]),g(De,ct)};U(je,De=>{a(T).gesture==="chord"&&a(T).subkey&&De(We)})}var lt=r(Ze,2),et=o(lt),Dt=r(Qe,2),ot=o(Dt),St=r(Dt,2),Yt=o(St),Ss=o(Yt),yt=r(Yt,2),He=r(yt,2);{var os=De=>{var ct=iu(),Vt=r(Ct(ct),2),R=r(Vt,2);K("click",Vt,()=>{M(a(T).id),f(u,null)}),K("click",R,()=>f(u,null)),g(De,ct)},Pt=De=>{var ct=ru();K("click",ct,()=>f(u,a(T).id,!0)),g(De,ct)};U(He,De=>{a(u)===a(T).id?De(os):De(Pt,-1)})}G((De,ct,Vt)=>{Se=ye(Z,1,"binding-item glass svelte-w4d8v7",null,Se,De),Oe=ye(me,1,"binding-title svelte-w4d8v7",null,Oe,ct),X(Ve,a(T).label||a(T).id),X(et,a(T).gesture),X(ot,Vt),X(Ss,a(T).disabled?"Enable":"Disable")},[()=>({disabled:a(T).disabled,"has-conflict":a(T).keys&&a(T).keys.length>0&&a(D).has(S(a(T).keys,a(T).gesture,a(T).subkey)),"active-conflict":!a(T).disabled&&a(T).keys&&a(T).keys.length>0&&a(V).has(S(a(T).keys,a(T).gesture,a(T).subkey))}),()=>({"has-conflict":!a(T).disabled&&a(T).keys&&a(T).keys.length>0&&a(V).has(S(a(T).keys,a(T).gesture,a(T).subkey))}),()=>H(a(T))]),K("click",Yt,()=>w(a(T).id)),K("click",yt,()=>ue(a(T))),g(A,Z)},A=>{var T=ou();g(A,T)});var P=r(ve,2);{var Y=A=>{var T=Au(),Z=o(T),Se=o(Z),ut=o(Se),zt=o(ut),qt=r(ut,2),_s=r(Se,2),le=o(_s),me=r(o(le),2),Oe=r(le,2),Ve=r(o(Oe),2),Ge=r(Oe,2),dt=o(Ge),Qe=r(o(dt),2),Ze=r(dt,2);ht(Ze,21,()=>a(i).target_ids||[],ft,(be,Ce,Le)=>{var Ke=vu(),At=o(Ke),Pe=o(At),ze=o(Pe),ke=r(Pe,2);{var st=Je=>{var Ne=uu(),bs=Ct(Ne),Gs=r(bs,2),vn=o(Gs);ht(vn,17,()=>a(e),ft,(pn,qa)=>{var fn=cu(),ol=o(fn);G(hn=>{var Ni,Ri;fn.disabled=hn,X(ol,`${(Ni=a(qa).label)!=null?Ni:""} (${(Ri=a(qa).delivery)!=null?Ri:""})`)},[()=>a(i).target_ids.includes(a(qa).id)&&a(qa).id!==a(Ce)]),K("click",fn,hn=>{hn.preventDefault(),hn.stopPropagation(),a(i).target_ids[Le]=a(qa).id,f(h,null)}),g(pn,fn)});var ll=r(vn,2);K("click",bs,()=>f(h,null)),K("click",ll,pn=>{pn.preventDefault(),pn.stopPropagation(),f(h,null),ie(Le)}),g(Je,Ne)};U(ke,Je=>{a(h)===Le&&Je(st)})}var wt=r(At,2);{var Jt=Je=>{var Ne=du();K("click",Ne,()=>q(Le)),g(Je,Ne)};U(wt,Je=>{Le>0&&Je(Jt)})}G(Je=>X(ze,Je),[()=>se(a(Ce))]),K("click",Pe,()=>f(h,a(h)===Le?null:Le,!0)),g(be,Ke)});var Ue=r(Ge,2),je=r(o(Ue),2);bt(je,{options:[{value:"hold",label:"Hold keys to dictate (Release to transcribe)"},{value:"toggle",label:"Tap once to start recording, tap again to finish"},{value:"double_tap",label:"Double-tap hotkey to trigger recording"},{value:"double_tap_hold",label:"Double-tap & hold keys to dictate (Release to transcribe)"},{value:"chord",label:"Chord combo (Held base keys + sub key)"}],get value(){return a(i).gesture},set value(be){a(i).gesture=be}});var We=r(Ue,2);{var lt=be=>{var Ce=pu(),Le=r(o(Ce),2);ge(Le,()=>a(i).hold_threshold_ms,Ke=>a(i).hold_threshold_ms=Ke),g(be,Ce)};U(We,be=>{(a(i).gesture==="hold"||a(i).gesture==="double_tap_hold")&&be(lt)})}var et=r(We,2);{var Dt=be=>{var Ce=fu(),Le=r(o(Ce),2);ge(Le,()=>a(i).tap_ms,Ke=>a(i).tap_ms=Ke),g(be,Ce)};U(et,be=>{(a(i).gesture==="double_tap"||a(i).gesture==="double_tap_hold")&&be(Dt)})}var ot=r(et,2),St=o(ot),Yt=o(St),Ss=o(Yt),yt=r(Yt,2),He=o(yt);{var os=be=>{var Ce=hu(),Le=r(o(Ce),2),Ke=o(Le);G(At=>X(Ke,At),[()=>a(z).length>0?a(z).join(" + ").replace(/KEY_/g,""):"Press your physical shortcut combination now..."]),g(be,Ce)},Pt=be=>{var Ce=bu(),Le=o(Ce);{var Ke=Pe=>{var ze=gu(),ke=Ct(ze);ht(ke,21,()=>a(i).keys,ft,(st,wt)=>{var Jt=_u(),Je=o(Jt);G(Ne=>X(Je,Ne),[()=>a(wt).replace("KEY_","")]),g(st,Jt)}),g(Pe,ze)},At=Pe=>{var ze=Ee("⚠️ Click/Focus here to press keys!");g(Pe,ze)};U(Le,Pe=>{a(i).keys.length>0?Pe(Ke):Pe(At,-1)})}g(be,Ce)};U(He,be=>{a(c)==="keys"?be(os):be(Pt,-1)})}var De=r(St,2);{var ct=be=>{var Ce=xu(),Le=r(o(Ce),2),Ke=o(Le);{var At=ze=>{var ke=mu();g(ze,ke)},Pe=ze=>{var ke=wu(),st=o(ke);{var wt=Je=>{var Ne=yu(),bs=Ct(Ne),Gs=o(bs);G(vn=>X(Gs,vn),[()=>a(i).subkey.replace("KEY_","")]),g(Je,Ne)},Jt=Je=>{var Ne=Ee("⚠️ Click/Focus here to press the trigger key!");g(Je,Ne)};U(st,Je=>{a(i).subkey?Je(wt):Je(Jt,-1)})}g(ze,ke)};U(Ke,ze=>{a(c)==="subkey"?ze(At):ze(Pe,-1)})}G(ze=>ye(Le,1,ze,"svelte-w4d8v7"),[()=>ps(["border-2 rounded-desktop p-4 text-center cursor-pointer outline-none transition-all duration-200 flex flex-col items-center justify-center min-h-[70px]",a(c)==="subkey"?"border-solid border-[#f43f5e] bg-[rgba(244,63,94,0.05)] animate-border-pulse":a($)?"border-solid border-[#fbbf24] bg-[rgba(251,191,36,0.05)] hover:border-[#fbbf24]/80":"border-dashed border-white/5 bg-black/25 hover:border-accent-blue hover:bg-black/35 focus:border-accent-blue focus:bg-black/35"].join(" "))]),K("click",Le,()=>f(c,"subkey")),Ms("focus",Le,()=>f(c,"subkey")),Ms("blur",Le,()=>ce()),K("keydown",Le,I),K("keyup",Le,Q),g(be,Ce)};U(De,be=>{a(i).gesture==="chord"&&be(ct)})}var Vt=r(De,2);{var R=be=>{var Ce=ku();g(be,Ce)};U(Vt,be=>{a($)&&be(R)})}var _e=r(ot,2),we=r(o(_e),2),tt=o(we),Mt=r(we,2);{var Gt=be=>{var Ce=Su(),Le=o(Ce),Ke=r(o(Le),2),At=r(Le,2),Pe=r(o(At),2);la(()=>ge(Pe,()=>a(k),Ne=>f(k,Ne))),ua(Pe,Ne=>F==null?void 0:F(Ne));var ze=r(At,2),ke=r(o(ze),2);_t(ke,"placeholder","e.g. write a haiku about {text}"),la(()=>ge(ke,()=>a(C),Ne=>f(C,Ne))),ua(ke,Ne=>F==null?void 0:F(Ne));var st=r(ke,2);{var wt=Ne=>{var bs=Tu(),Gs=r(o(bs));Gs.textContent="{text}",g(Ne,bs)},Jt=he(()=>a(C)&&!a(C).includes("{text}")),Je=Ne=>{var bs=Eu(),Gs=r(o(bs));Gs.textContent="{text}",g(Ne,bs)};U(st,Ne=>{a(Jt)?Ne(wt):Ne(Je,-1)})}G(Ne=>ye(ke,1,Ne,"svelte-w4d8v7"),[()=>ps(a(C)&&!a(C).includes("{text}")?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":"")]),ge(Ke,()=>a(x),Ne=>f(x,Ne)),g(be,Ce)};U(Mt,be=>{a(v)&&be(Gt)})}var gs=r(_s,2),Rs=o(gs),Ys=r(Rs,2);G(be=>{X(zt,a(l)?"Create Hotkey Binding":"Edit Hotkey Binding"),me.disabled=!a(l),X(Ss,a(i).gesture==="chord"?"Base Combo (Held Keys)":"Hotkey Keybind Selection"),ye(yt,1,be,"svelte-w4d8v7")},[()=>ps(["border-2 rounded-desktop p-4 text-center cursor-pointer outline-none transition-all duration-200 flex flex-col items-center justify-center min-h-[70px]",a(c)==="keys"?"border-solid border-[#f43f5e] bg-[rgba(244,63,94,0.05)] animate-border-pulse":a($)?"border-solid border-[#fbbf24] bg-[rgba(251,191,36,0.05)] hover:border-[#fbbf24]/80":"border-dashed border-white/5 bg-black/25 hover:border-accent-blue hover:bg-black/35 focus:border-accent-blue focus:bg-black/35"].join(" "))]),K("click",qt,()=>{f(i,null),f(c,null)}),ge(me,()=>a(i).id,be=>a(i).id=be),ge(Ve,()=>a(i).label,be=>a(i).label=be),K("click",Qe,J),K("click",yt,()=>f(c,"keys")),Ms("focus",yt,()=>f(c,"keys")),Ms("blur",yt,()=>ce()),K("keydown",yt,I),K("keyup",yt,Q),Xe(tt,()=>a(v),be=>f(v,be)),K("click",Rs,()=>{f(i,null),f(c,null)}),K("click",Ys,N),g(A,T)};U(P,A=>{a(i)&&A(Y)})}var te=r(P,2);{var de=A=>{il(A,{isNew:!0,get existingTargets(){return a(e)},isNested:!0,onSave:ee,onCancel:W,get editingTarget(){return a(d)},set editingTarget(T){f(d,T,!0)}})};U(te,A=>{a(d)&&A(de)})}K("click",re,oe),g(s,ae),Ye()}Wt(["click","keydown","keyup"]);var Mu=E('
'),Ou=E('
'),Iu=E('
'),Du=E('
'),Lu=E('
'),Nu=E('
'),Ru=E('
Speech: Plays transcribed text via TTS
'),Fu=E('Delete? ',1),Wu=E(''),zu=E('
'),qu=E('
🎯

No output targets defined. Create one to route your transcription output!

'),Vu=E('

Output Targets

Define routing destinations where transcribed text is typed, copied, piped, or sent over network sockets.

',1);function Bu(s,t){$e(t,!0);let e=B(Be([])),n=B(Be([])),i=B(null),l=B(!1),c=B(null),u=B(null);rt(async()=>{f(e,await O("get_targets"),!0),f(n,await O("get_bindings"),!0)});async function d(){try{await O("save_targets",{targets:a(e)}),console.log("Targets auto-saved successfully!")}catch(F){console.error("Failed to save targets:",F)}}async function p(){try{await O("save_bindings",{bindings:a(n)}),console.log("Bindings auto-saved successfully!")}catch(F){console.error("Failed to save bindings:",F)}}function _(){f(l,!0),f(i,{id:"new_target_"+Math.random().toString(36).substring(2,6),label:"New Target",delivery:"inject",file_prefix:"- ",file_timestamp:!0,file_mode:"append",http_method:"POST",http_json_template:{text:"{text}"},webhook_json_template:{text:"{text}"},mcp_tool:"speak_text",mcp_args:{text:"{text}"},send_on_release:!1,append_newline:!0,strip_newlines:!1,processing:{apply_snippets:!0}},!0)}function h(F){f(l,!1),f(c,F.id,!0);const b=JSON.parse(JSON.stringify(F));b.processing||(b.processing={}),b.file_mode||(b.file_mode="append"),f(i,b,!0)}function v(){f(i,null),f(c,null)}async function x(){if(a(i)){if(a(l))f(e,[...a(e),a(i)],!0);else{if(a(c)&&a(c)!==a(i).id){let F=!1;f(n,a(n).map(b=>{let L=!1,H=b.target_ids?[...b.target_ids]:[b.target_id];for(let se=0;seF.id===a(c)?a(i):F),!0)}f(i,null),f(c,null),await d()}}async function y(F){const b=a(n).filter(L=>(L.target_ids&&L.target_ids.length>0?L.target_ids:[L.target_id]).includes(F)).map(L=>L.label||L.id);if(b.length>0){alert(`Cannot delete target. It is currently being used by hotkeys: ${b.join(", ")}`);return}f(e,a(e).filter(L=>L.id!==F),!0),await d()}var C=Vu(),k=Ct(C),S=r(o(k),2),D=r(S,2);ht(D,21,()=>a(e),ft,(F,b)=>{var L=zu(),H=o(L),se=o(H),oe=o(se),ue=o(oe),w=r(oe,2),J=o(w),q=r(se,2);{var N=te=>{var de=Mu(),A=o(de);G(()=>{var T;return X(A,`Cmd: ${(T=a(b).command)!=null?T:""}`)}),g(te,de)};U(q,te=>{a(b).delivery==="exec"&&te(N)})}var M=r(q,2);{var j=te=>{var de=Ou(),A=o(de);G(()=>{var T;return X(A,`File: ${(T=a(b).file_path)!=null?T:""}`)}),g(te,de)};U(M,te=>{a(b).delivery==="file"&&te(j)})}var z=r(M,2);{var I=te=>{var de=Iu(),A=o(de);G(()=>{var T,Z;return X(A,`Socket: ${(T=a(b).socket_host)!=null?T:""}:${(Z=a(b).socket_port)!=null?Z:""}`)}),g(te,de)};U(z,te=>{a(b).delivery==="socket"&&te(I)})}var Q=r(z,2);{var ce=te=>{var de=Du(),A=o(de),T=r(A);{var Z=Se=>{var ut=Ee();G(()=>{var zt;return X(ut,`→ ${(zt=a(b).response_pipe)!=null?zt:""}`)}),g(Se,ut)};U(T,Se=>{a(b).response_pipe&&Se(Z)})}G(()=>{var Se;return X(A,`Pipe: ${(Se=a(b).pipe_path)!=null?Se:""} `)}),g(te,de)};U(Q,te=>{a(b).delivery==="pipe"&&te(ce)})}var ie=r(Q,2);{var W=te=>{var de=Lu(),A=o(de);G(()=>{var T;return X(A,`API: ${(T=a(b).http_url||a(b).webhook_url)!=null?T:""}`)}),g(te,de)};U(ie,te=>{(a(b).delivery==="http"||a(b).delivery==="webhook")&&te(W)})}var ee=r(ie,2);{var ae=te=>{var de=Nu(),A=o(de);G(()=>{var T;return X(A,`MCP Tool: ${(T=a(b).mcp_tool||"speak_text")!=null?T:""}`)}),g(te,de)};U(ee,te=>{a(b).delivery==="mcp"&&te(ae)})}var ve=r(ee,2);{var re=te=>{var de=Ru();g(te,de)};U(ve,te=>{a(b).delivery==="speak"&&te(re)})}var ne=r(ve,2),pe=o(ne),Ie=r(pe,2);{var P=te=>{var de=Fu(),A=r(Ct(de),2),T=r(A,2);K("click",A,()=>{y(a(b).id),f(u,null)}),K("click",T,()=>f(u,null)),g(te,de)},Y=te=>{var de=Wu();K("click",de,()=>f(u,a(b).id,!0)),g(te,de)};U(Ie,te=>{a(u)===a(b).id?te(P):te(Y,-1)})}G(()=>{X(ue,a(b).label),X(J,a(b).delivery)}),K("click",pe,()=>h(a(b))),g(F,L)},F=>{var b=qu();g(F,b)});var V=r(k,2);{var $=F=>{il(F,{get isNew(){return a(l)},get existingTargets(){return a(e)},isNested:!1,onSave:x,onCancel:v,get editingTarget(){return a(i)},set editingTarget(b){f(i,b,!0)}})};U(V,F=>{a(i)&&F($)})}K("click",S,_),g(s,C),Ye()}Wt(["click"]);var Uu=E('

Use CUDA GPU acceleration (ONNX Runtime). Falls back to CPU if unavailable.

',1),ju=E('
Run speed
'),Hu=E('

'),Ku=E('⏳ Checking local voice files...'),$u=E(' '),Yu=E('
'),Gu=E('

'),Ju=E('

Piper Voice

Voice directory (leave blank for default)

Default voice directory: ~/.local/share/voxctrl/piper-voices/

'),Zu=E('⏳ Checking local model files...'),Xu=E('⏳ Downloading Pocket-TTS model & voice clip (may take a few minutes)...'),Qu=E('
'),ed=E('

'),td=E(`

Pocket-TTS Voice

HuggingFace access token

Pocket-TTS model weights are hosted on a gated HuggingFace repo. Create a token at huggingface.co/settings/tokens and accept the license at huggingface.co/kyutai/pocket-tts before downloading.

Custom voice directory (leave blank for default)

Drop a .wav reference clip into this folder to add it to the voice list — - the filename (without extension) becomes the voice's id, e.g. narrator.wav adds - "Narrator (Custom)". Naming a clip after a built-in voice (e.g. alba.wav) replaces - that voice's reference clip. Default: ~/.local/share/voxctrl/pocket-tts-voices/

`),sd=E('
'),ad=E(' '),nd=E('
(Click / Tab here to record a new stop key)',1),id=E(''),rd=E('

Text to Speech

TTS Engine

Playback

Stop Key Bind

Press a key combo to immediately stop TTS playback — works even when this window is hidden.

');function ld(s,t){$e(t,!0);let e=qe(t,"cfg",15);function n(){Es.set(!0)}let i=B(null),l=B(0),c=B(!1),u=null,d=null,p=null,_=null,h=B(!1),v=B(null),x=0;function y(){f(c,!0),f(l,0),f(i,null),x=performance.now(),u&&clearInterval(u),u=setInterval(()=>{f(l,Math.round(performance.now()-x),!0),a(l)>1e4&&(clearInterval(u),f(c,!1),f(i,null))},10)}const C=["en-us-libritts-high","en-us-amy-low","en-us-kathleen-low","en-gb-southern_english_female-low","en-us-ryan-high","en-us-ryan-medium","en-us-ryan-low","en-us-lessac-medium","en-us-lessac-low","en-us-danny-low","en-gb-alan-low"];let k=B(Be({})),S=B(!1),D=B(!1),V=B(!1),$=B(null);async function F(){f(S,!0);const R={};for(const _e of C)try{R[_e]=await O("check_voice_downloaded",{voiceName:_e,voiceDir:e().tts.voice_dir})}catch(we){console.error("Failed to check download status for voice "+_e,we),R[_e]=!1}f(k,R,!0),f(S,!1)}async function b(R){if(!a(D)){f(D,!0);try{await O("download_voice",{voiceName:R,voiceDir:e().tts.voice_dir}),a(k)[R]=!0}catch(_e){alert(`Failed to download voice: ${_e}`)}finally{f(D,!1)}}}async function L(){const R=e().tts.voice_dir;if(!R){f($,null);return}const _e=await O("check_directory_exists",{path:R});f($,_e?null:"This folder does not exist. Please create it first or leave blank for the default location.",!0),a($)||await F()}function H(){n()}function se(R){R.key==="Enter"&&R.currentTarget.blur()}async function oe(){n()}async function ue(){if(a(V))return;if(a(h)){f(h,!1);try{await O("stop_tts")}catch(tt){console.error("Failed to stop TTS:",tt)}}f(V,!0),f(v,null),y();let R="TTS",_e=null;e().tts.engine==="piper"?(R="Piper",_e=e().tts.voice):e().tts.engine==="pocket_tts"?(R="Pocket-TTS",_e=e().tts.pocket_tts.voice):e().tts.engine==="espeak"&&(R="eSpeak-NG",_e=null);const we=`Hi this is ${R} speaking from VoxCtrl`;try{await O("speak_text",{text:we,voice:_e})}catch(tt){f(v,`${tt}`),clearInterval(u),f(c,!1),f(V,!1)}}let w=B(!1);function J(){return!e().tts.enabled||a(w)?!0:a(h)?!1:a(V)?!0:e().tts.engine==="piper"?a(S)||a(D)||!a(k)[e().tts.voice]:e().tts.engine==="pocket_tts"?a(ee)||a(ae)||!a(W):!1}let q=B(Be([])),N=B(null);async function M(){try{f(q,await O("list_pocket_tts_voices",{voiceDir:e().tts.pocket_tts.voice_dir}),!0)}catch(R){console.error("list_pocket_tts_voices:",R)}}async function j(){const R=e().tts.pocket_tts.voice_dir;if(!R){f(N,null),await M();return}const _e=await O("check_directory_exists",{path:R});f(N,_e?null:"This folder does not exist. Please create it first or leave blank for the default location.",!0),a(N)||await M()}function z(){n()}function I(R){R.key==="Enter"&&R.currentTarget.blur()}let Q=he(()=>C.map(R=>({value:R,label:`${R}${a(k)[R]?" ✔":""}`}))),ce=he(()=>a(q).map(R=>({value:R.id,label:R.label})));const ie=[{value:"pocket_tts",label:"Pocket-TTS (neural, voice cloning)"},{value:"piper",label:"Piper (neural, high quality)"},{value:"espeak",label:"eSpeak-NG (lightweight)"}];let W=B(!1),ee=B(!1),ae=B(!1);async function ve(){f(ee,!0);try{f(W,await O("check_pocket_tts_ready",{voice:e().tts.pocket_tts.voice,voiceDir:e().tts.pocket_tts.voice_dir}),!0)}catch(R){console.error("check_pocket_tts_ready:",R),f(W,!1)}finally{f(ee,!1)}}async function re(){if(!a(ae)){f(ae,!0);try{await O("download_pocket_tts",{voice:e().tts.pocket_tts.voice,voiceDir:e().tts.pocket_tts.voice_dir,hfToken:e().tts.pocket_tts.hf_token}),f(W,!0)}catch(R){alert(`Failed to download Pocket-TTS assets: ${R}`)}finally{f(ae,!1)}}}function ne(){n(),f(W,!1),ve()}function pe(){n()}async function Ie(){n(),f(w,!0);try{e().tts.engine==="pocket_tts"?(f(W,!1),await M(),await ve()):e().tts.engine==="piper"&&(e().tts.voice_dir?await L():await F())}finally{setTimeout(()=>{f(w,!1)},400)}}rt(async()=>{e().tts.voice_dir?L():F(),e().tts.engine==="pocket_tts"&&(await M(),ve()),d=await gt("tts-playback-start",()=>{a(c)&&(clearInterval(u),f(i,a(l),!0),f(c,!1)),f(V,!1),f(h,!0)}),p=await gt("tts-playback-end",()=>{f(h,!1)}),_=await gt("tts-error",R=>{f(v,R.payload,!0),clearInterval(u),f(c,!1),f(i,null),f(V,!1),f(h,!1)})}),Qr(()=>{u&&clearInterval(u),d&&d(),p&&p(),_&&_()});let P=B(!1),Y=B(Be([]));function te(R,_e){const we=_e.toUpperCase();return R==="Control"?"KEY_LEFTCTRL":R==="Alt"?"KEY_LEFTALT":R==="Shift"?"KEY_LEFTSHIFT":R==="Meta"||R==="OS"||R==="Super"?"KEY_LEFTMETA":we==="SPACE"?"KEY_SPACE":we==="ENTER"?"KEY_ENTER":we==="ESCAPE"||we==="ESC"?"KEY_ESC":we==="TAB"?"KEY_TAB":we==="BACKSPACE"?"KEY_BACKSPACE":we==="DELETE"?"KEY_DELETE":we.startsWith("KEY")?we:we.startsWith("DIGIT")?`KEY_${we.replace("DIGIT","")}`:we.startsWith("ARROW")?`KEY_${we.replace("ARROW","")}`:we.startsWith("F")&&we.length>1?`KEY_${we}`:R.length===1?`KEY_${R.toUpperCase()}`:`KEY_${we}`}function de(R){if(!a(P))return;R.preventDefault(),R.stopPropagation();const _e=te(R.key,R.code);a(Y).includes(_e)||f(Y,[...a(Y),_e],!0),R.key==="Escape"&&(e(e().tts.stop_key=[...a(Y)],!0),n(),f(Y,[],!0),f(P,!1))}function A(R){a(P)&&(R.preventDefault(),R.stopPropagation(),a(Y).length>0&&(e(e().tts.stop_key=[...a(Y)],!0),n()),f(Y,[],!0),f(P,!1))}function T(){a(Y).length>0&&(e(e().tts.stop_key=[...a(Y)],!0),n(),f(Y,[],!0)),f(P,!1)}var Z=rd(),Se=r(o(Z),2),ut=r(o(Se),2),zt=r(o(ut),2),qt=r(ut,2),_s=r(o(qt),2);bt(_s,{get options(){return ie},onchange:Ie,get value(){return e().tts.engine},set value(R){e(e().tts.engine=R,!0)}});var le=r(qt,2);{var me=R=>{var _e=Uu(),we=Ct(_e),tt=r(o(we),2);K("change",tt,n),Xe(tt,()=>e().tts.gpu,Mt=>e(e().tts.gpu=Mt,!0)),g(R,_e)};U(le,R=>{e().tts.engine==="piper"&&R(me)})}var Oe=r(le,2),Ve=o(Oe),Ge=o(Ve),dt=r(Ve,2),Qe=r(Oe,2),Ze=o(Qe),Ue=o(Ze),je=r(Ze,2);{var We=R=>{var _e=ju(),we=r(o(_e),2);let tt;var Mt=o(we);G(()=>{tt=ye(we,1,"run-speed-value svelte-1q9seip",null,tt,{counting:a(c)}),X(Mt,a(c)?`${a(l)} ms`:`${a(i)} ms`)}),g(R,_e)};U(je,R=>{(a(c)||a(i)!==null)&&R(We)})}var lt=r(Qe,2);{var et=R=>{var _e=Hu(),we=o(_e);G(()=>{var tt;return X(we,`❌ ${(tt=a(v))!=null?tt:""}`)}),g(R,_e)};U(lt,R=>{a(v)&&R(et)})}var Dt=r(Se,2);{var ot=R=>{var _e=Ju(),we=r(o(_e),2),tt=r(o(we),2);bt(tt,{get options(){return a(Q)},onchange:oe,get value(){return e().tts.voice},set value(Pe){e(e().tts.voice=Pe,!0)}});var Mt=r(we,2),Gt=o(Mt);{var gs=Pe=>{var ze=Ku();g(Pe,ze)},Rs=Pe=>{var ze=$u(),ke=o(ze);G(()=>{var st;return X(ke,`⏳ Downloading ${(st=e().tts.voice)!=null?st:""} (model + config)...`)}),g(Pe,ze)},Ys=Pe=>{var ze=Yu(),ke=o(ze),st=o(ke),wt=r(ke,2),Jt=o(wt);G(()=>{ye(ke,1,ps(a(k)[e().tts.voice]?"status-downloaded":"status-missing"),"svelte-1q9seip"),X(st,a(k)[e().tts.voice]?"✔ Voice downloaded and ready":"❌ Voice files missing"),wt.disabled=a(k)[e().tts.voice]||a(D),X(Jt,a(k)[e().tts.voice]?"Downloaded":"📥 Download")}),K("click",wt,()=>b(e().tts.voice)),g(Pe,ze)};U(Gt,Pe=>{a(S)?Pe(gs):a(D)?Pe(Rs,1):Pe(Ys,-1)})}var be=r(Mt,2),Ce=r(o(be),2);let Le;var Ke=r(Ce,2);{var At=Pe=>{var ze=Gu(),ke=o(ze);G(()=>X(ke,a($))),g(Pe,ze)};U(Ke,Pe=>{a($)&&Pe(At)})}G(()=>Le=ye(Ce,1,"svelte-1q9seip",null,Le,{"field-input-error":!!a($)})),K("change",Ce,H),Ms("blur",Ce,L),K("keydown",Ce,se),ge(Ce,()=>e().tts.voice_dir,Pe=>e(e().tts.voice_dir=Pe,!0)),g(R,_e)};U(Dt,R=>{e().tts.engine==="piper"&&R(ot)})}var St=r(Dt,2);{var Yt=R=>{var _e=td(),we=r(o(_e),2),tt=r(o(we),2);bt(tt,{get options(){return a(ce)},onchange:ne,get value(){return e().tts.pocket_tts.voice},set value(ke){e(e().tts.pocket_tts.voice=ke,!0)}});var Mt=r(we,2),Gt=o(Mt);{var gs=ke=>{var st=Zu();g(ke,st)},Rs=ke=>{var st=Xu();g(ke,st)},Ys=ke=>{var st=Qu(),wt=o(st),Jt=o(wt),Je=r(wt,2),Ne=o(Je);G(()=>{ye(wt,1,ps(a(W)?"status-downloaded":"status-missing"),"svelte-1q9seip"),X(Jt,a(W)?"✔ Model and voice clip downloaded and ready":"❌ Model files missing"),Je.disabled=a(W)||a(ae),X(Ne,a(W)?"Downloaded":"📥 Download")}),K("click",Je,re),g(ke,st)};U(Gt,ke=>{a(ee)?ke(gs):a(ae)?ke(Rs,1):ke(Ys,-1)})}var be=r(Mt,2),Ce=r(o(be),2),Le=r(be,4),Ke=r(o(Le),2);let At;var Pe=r(Ke,2);{var ze=ke=>{var st=ed(),wt=o(st);G(()=>X(wt,a(N))),g(ke,st)};U(Pe,ke=>{a(N)&&ke(ze)})}G(()=>At=ye(Ke,1,"svelte-1q9seip",null,At,{"field-input-error":!!a(N)})),K("change",Ce,pe),ge(Ce,()=>e().tts.pocket_tts.hf_token,ke=>e(e().tts.pocket_tts.hf_token=ke,!0)),K("change",Ke,z),Ms("blur",Ke,j),K("keydown",Ke,I),ge(Ke,()=>e().tts.pocket_tts.voice_dir,ke=>e(e().tts.pocket_tts.voice_dir=ke,!0)),g(R,_e)};U(St,R=>{e().tts.engine==="pocket_tts"&&R(Yt)})}var Ss=r(St,2),yt=r(o(Ss),2),He=r(o(yt),2),os=r(yt,2),Pt=r(o(os),4),De=o(Pt);{var ct=R=>{var _e=sd(),we=r(o(_e),2),tt=o(we);G(Mt=>X(tt,Mt),[()=>a(Y).length>0?a(Y).join(" + ").replace(/KEY_/g,""):"Press your physical shortcut combination now..."]),g(R,_e)},Vt=R=>{var _e=id(),we=o(_e);{var tt=Gt=>{var gs=nd(),Rs=Ct(gs);ht(Rs,21,()=>e().tts.stop_key,ft,(Ys,be)=>{var Ce=ad(),Le=o(Ce);G(Ke=>X(Le,Ke),[()=>a(be).replace("KEY_","")]),g(Ys,Ce)}),g(Gt,gs)},Mt=Gt=>{var gs=Ee("⚠️ Click/Focus here to press a stop key!");g(Gt,gs)};U(we,Gt=>{e().tts.stop_key.length>0?Gt(tt):Gt(Mt,-1)})}g(R,_e)};U(De,R=>{a(P)?R(ct):R(Vt,-1)})}G((R,_e,we)=>{X(Ge,`Speed (${R!=null?R:""}×)`),Ze.disabled=_e,X(Ue,a(V)?"Speaking...":a(h)?"⏹ Stop & Test":"Test TTS"),ye(Pt,1,we,"svelte-1q9seip")},[()=>e().tts.speed.toFixed(2),()=>J(),()=>ps(["border-2 rounded-desktop p-6 text-center cursor-pointer outline-none transition-all duration-200 flex flex-col items-center justify-center min-h-[80px]",a(P)?"border-solid border-[#f43f5e] bg-[rgba(244,63,94,0.05)] animate-border-pulse":"border-dashed border-white/5 bg-black/25 hover:border-accent-blue hover:bg-black/35 focus:border-accent-blue focus:bg-black/35"].join(" "))]),K("change",zt,n),Xe(zt,()=>e().tts.enabled,R=>e(e().tts.enabled=R,!0)),K("change",dt,n),ge(dt,()=>e().tts.speed,R=>e(e().tts.speed=R,!0)),K("click",Ze,ue),K("change",He,n),Xe(He,()=>e().tts.response_overlay,R=>e(e().tts.response_overlay=R,!0)),K("click",Pt,()=>f(P,!0)),Ms("focus",Pt,()=>f(P,!0)),Ms("blur",Pt,T),K("keydown",Pt,de),K("keyup",Pt,A),g(s,Z),Ye()}Wt(["change","click","keydown","keyup"]);var od=E(''),cd=E(`⚠️ The model isn't available on this server. Post-processing will fail with a 404 — pick a model from the list above or pull it on the server.`),ud=E(" "),dd=E('Select the Custom preset to edit the system and user prompts.'),vd=E('⚠️ The user prompt must contain the placeholder.'),pd=E('Use where your dictated speech should be inserted.'),fd=E(`

OpenAI API LLM Post-Processing

Connect to any OpenAI-compatible API server — a local server or a hosted - provider. The URL defaults to a local server; point it anywhere you like and - supply an API key when the server requires one.

Connection

Default Prompts

The system prompt tells the model how to transform your speech. The user - prompt is the message sent to the model — it must contain , which is replaced with whatever you dictate. - Built-in presets are read-only; choose Custom to edit the - prompts yourself.

System Prompt
User Prompt
`);function hd(s,t){$e(t,!0);let e=qe(t,"cfg",15);function n(){Es.set(!0)}let i=B(!1),l=B(null),c=B(Be([])),u=he(()=>[...a(c).map(P=>({value:P,label:P})),...e().openai.model&&!a(c).includes(e().openai.model)?[{value:e().openai.model,label:`${e().openai.model} (not found)`}]:[]]);const d=[{value:"clean",label:"Clean (grammar fix)"},{value:"formal",label:"Formal"},{value:"casual",label:"Casual"},{value:"bullet",label:"Bullet points"},{value:"concise",label:"Concise (summarize)"},{value:"custom",label:"Custom (editable)"}],p={clean:"Fix grammar and punctuation only. Return only the corrected text, no commentary.",formal:"Rewrite the user's text in formal professional language. Return only the result.",casual:"Rewrite the user's text in casual conversational language. Return only the result.",bullet:"Convert the user's text to a bullet-point list. Return only the list.",concise:"Summarize the user's text concisely in 1-2 sentences. Return only the summary."};let _=he(()=>e().openai.mode==="custom");function h(){const P=p[e().openai.mode];P!==void 0&&(e(e().openai.system_prompt=P,!0),e(e().openai.user_prompt="{text}",!0)),n()}let v=he(()=>e().openai.user_prompt.includes("{text}")),x=he(()=>a(c).length>0&&!!e().openai.model&&!a(c).includes(e().openai.model));async function y(){f(i,!0),f(l,null);try{const P=await O("test_openai",{endpoint:e().openai.endpoint,apiKey:e().openai.api_key,timeoutSecs:e().openai.timeout_secs});f(l,{success:P.success,message:P.message},!0),P.success&&(f(c,P.models,!0),!e().openai.model&&P.models.length>0&&(e(e().openai.model=P.models[0],!0),n()))}catch(P){f(l,{success:!1,message:P.toString()},!0)}finally{f(i,!1)}}rt(()=>{y()});var C=fd(),k=r(o(C),4),S=r(o(k),2),D=r(o(S),2),V=r(S,2),$=r(o(V),2),F=r(V,2),b=r(o(F),2);{var L=P=>{bt(P,{get options(){return a(u)},onchange:n,get value(){return e().openai.model},set value(Y){e(e().openai.model=Y,!0)}})},H=P=>{var Y=od();K("change",Y,n),ge(Y,()=>e().openai.model,te=>e(e().openai.model=te,!0)),g(P,Y)};U(b,P=>{a(c).length>0?P(L):P(H,-1)})}var se=r(F,2);{var oe=P=>{var Y=cd(),te=r(o(Y)),de=o(te);G(()=>X(de,e().openai.model)),g(P,Y)};U(se,P=>{a(x)&&P(oe)})}var ue=r(se,2),w=r(o(ue),2),J=r(ue,2),q=o(J),N=o(q),M=r(q,2);{var j=P=>{var Y=ud(),te=o(Y);G(()=>{ye(Y,1,`status-msg ${a(l).success?"success":"error"}`,"svelte-1bvctpo"),X(te,a(l).message)}),g(P,Y)};U(M,P=>{a(l)&&P(j)})}var z=r(k,2),I=r(o(z),2),Q=r(o(I));Q.textContent="{text}";var ce=r(I,2),ie=r(o(ce),2);bt(ie,{get options(){return d},onchange:h,get value(){return e().openai.mode},set value(P){e(e().openai.mode=P,!0)}});var W=r(ce,2),ee=r(o(W),2),ae=r(W,2),ve=r(o(ae),2);_t(ve,"placeholder","{text}");var re=r(ve,2);{var ne=P=>{var Y=dd();g(P,Y)},pe=P=>{var Y=vd(),te=r(o(Y));te.textContent="{text}",g(P,Y)},Ie=P=>{var Y=pd(),te=r(o(Y));te.textContent="{text}",g(P,Y)};U(re,P=>{a(_)?a(v)?P(Ie,-1):P(pe,1):P(ne)})}G(()=>{q.disabled=a(i),X(N,a(i)?"⏳ Testing...":"🔌 Test Connection"),ee.readOnly=!a(_),ye(ee,1,ps(a(_)?"":"locked"),"svelte-1bvctpo"),ve.readOnly=!a(_),ye(ve,1,ps(a(_)?a(v)?"":"invalid":"locked"),"svelte-1bvctpo")}),K("change",D,n),ge(D,()=>e().openai.endpoint,P=>e(e().openai.endpoint=P,!0)),K("change",$,n),ge($,()=>e().openai.api_key,P=>e(e().openai.api_key=P,!0)),K("change",w,n),ge(w,()=>e().openai.timeout_secs,P=>e(e().openai.timeout_secs=P,!0)),K("click",q,y),K("change",ee,n),ge(ee,()=>e().openai.system_prompt,P=>e(e().openai.system_prompt=P,!0)),K("change",ve,n),ge(ve,()=>e().openai.user_prompt,P=>e(e().openai.user_prompt=P,!0)),g(s,C),Ye()}Wt(["change","click"]);var _d=E('
'),gd=E('

No snippets defined.

'),bd=E('

Features & Post-Processing

Text cleanup

Custom Dictionary

Provide a comma-separated list of words (e.g. names or jargon like "Waylin, Rufer, Enola, Kenz") that are hard to spell. The transcription process will correct these in the final text.

Snippets

Type a trigger word → it expands to the replacement text.

');function md(s,t){$e(t,!0);let e=qe(t,"cfg",15);function n(){Es.set(!0)}let i=B(Be(Object.entries(e().features.snippets).map(([w,J])=>({key:w,val:J}))));function l(){const w={};for(const{key:J,val:q}of a(i))J.trim()&&(w[J.trim()]=q.trim());e(e().features.snippets=w,!0),n()}function c(){f(i,[...a(i),{key:"",val:""}],!0)}function u(w){f(i,a(i).filter((J,q)=>q!==w),!0),l()}let d=he(()=>e().features.custom_vocabulary?e().features.custom_vocabulary.join(", "):"");function p(w){const J=w.target;e(e().features.custom_vocabulary=J.value.split(",").map(q=>q.trim()).filter(q=>q.length>0),!0),n()}function _(w){function J(){w.style.height="auto",w.style.height=`${w.scrollHeight}px`}w.addEventListener("input",J);const q=setTimeout(J,0);return{update(){J()},destroy(){clearTimeout(q),w.removeEventListener("input",J)}}}var h=bd(),v=r(o(h),2),x=r(o(v),2),y=r(o(x),2),C=r(x,2),k=r(o(C),2),S=r(C,2),D=r(o(S),2),V=r(v,2),$=r(o(V),4);ua($,w=>_==null?void 0:_(w));var F=r(V,2),b=o(F),L=r(o(b),2),H=r(b,2),se=o(H);ht(se,17,()=>a(i),ft,(w,J,q)=>{var N=_d(),M=o(N),j=r(M,4),z=r(j,2);K("input",M,l),ge(M,()=>a(i)[q].key,I=>a(i)[q].key=I),K("input",j,l),ge(j,()=>a(i)[q].val,I=>a(i)[q].val=I),K("click",z,()=>u(q)),g(w,N)});var oe=r(se,2);{var ue=w=>{var J=gd();g(w,J)};U(oe,w=>{a(i).length===0&&w(ue)})}G(()=>Go($,a(d))),K("change",y,n),Xe(y,()=>e().features.remove_fillers,w=>e(e().features.remove_fillers=w,!0)),K("change",k,n),Xe(k,()=>e().features.spoken_punctuation,w=>e(e().features.spoken_punctuation=w,!0)),K("change",D,n),Xe(D,()=>e().features.auto_format_lists,w=>e(e().features.auto_format_lists=w,!0)),K("input",$,p),K("click",L,c),g(s,h),Ye()}Wt(["change","input","click"]);class Ja extends nc{constructor(t){super(t)}static async new(t,e,n){return O("plugin:image|new",{rgba:In(t),width:e,height:n}).then(i=>new Ja(i))}static async fromBytes(t){return O("plugin:image|from_bytes",{bytes:In(t)}).then(e=>new Ja(e))}static async fromPath(t){return O("plugin:image|from_path",{path:t}).then(e=>new Ja(e))}async rgba(){return O("plugin:image|rgba",{rid:this.rid}).then(t=>new Uint8Array(t))}async size(){return O("plugin:image|size",{rid:this.rid})}}function In(s){return s==null?null:typeof s=="string"?s:s instanceof Ja?s.rid:s}var Ji;(function(s){s.Nsis="nsis",s.Msi="msi",s.Deb="deb",s.Rpm="rpm",s.AppImage="appimage",s.App="app"})(Ji||(Ji={}));async function yd(){return O("plugin:app|version")}const wd="/assets/voxctrl-CDHFw5hI.gif";var xd=E(`

About VoxCtrl

VoxCtrl

Native, on-device voice-to-text for Linux and Windows. - Uses whisper.cpp and Moonshine for offline transcription and routes speech to any destination.

System

FrontendSvelte 5 + Tauri 2
BackendRust (Tokio async)
Inferencewhisper.cpp & Moonshine
Config~/.config/voxctrl/
Models~/.local/share/voxctrl/models/
MCP socket/tmp/voxctrl-mcp.sock

Open Source Attributions

This application is built possible by these outstanding open-source projects:

whisper.cpp MIT License
Tauri Framework MIT / Apache 2.0
Svelte & Vite MIT License
Piper TTS MIT License
Pocket-TTS (Kyutai Labs) MIT / Apache 2.0
Candle MIT / Apache 2.0
whisper-rs MIT License
Rust, Tokio & CPAL MIT / Apache 2.0
`);function kd(s,t){$e(t,!0);let e=B("0.1.0");rt(async()=>{try{f(e,await yd(),!0)}catch(p){console.error("Failed to fetch app version:",p)}});var n=xd(),i=r(o(n),2),l=o(i),c=r(l,2),u=r(o(c),2),d=o(u);G(()=>{var p;_t(l,"src",wd),X(d,`Version ${(p=a(e))!=null?p:""} — Rust + Tauri Edition`)}),g(s,n),Ye()}var Td=E(''),Ed=E(''),Sd=E(' 🛑 Stop',1),Ad=E('🎙️ Record'),Cd=E('
Unsaved changes detected
'),Pd=E('
');function Md(s,t){$e(t,!0);const e=()=>kt($t,"$config",l),n=()=>kt(Et,"$status",l),i=()=>kt(Es,"$configDirty",l),[l,c]=hs();let u=B("general");const d=[{id:"general",label:"General",icon:"⚙️"},{id:"engine",label:"Engine",icon:"🧠"},{id:"hotkeys",label:"Hotkeys",icon:"⌨️"},{id:"targets",label:"Output Targets",icon:"🎯"},{id:"visual",label:"Visual",icon:"🎨"},{id:"audio",label:"Audio",icon:"🔊"},{id:"tts",label:"TTS",icon:"🗣️"},{id:"features",label:"Features",icon:"✨"},{id:"openai",label:"OpenAI API",icon:"🤖"},{id:"about",label:"About",icon:"ℹ️"}];async function p(){await nl(e())}async function _(){await O("toggle_recording")}let h=a(u),v=B(null);ka(()=>{var Y,te;const P=a(u);P!==h&&(h=P,a(v)&&(a(v).scrollTop=0),(te=(Y=e())==null?void 0:Y.audio)!=null&&te.dynamic_stream&&n().recording&&O("stop_recording").catch(de=>{console.error("Failed to stop recording on activeTab change:",de)}))}),rt(()=>{let P;P=fi.subscribe(Y=>{if(Y){const te=e();if(te&&te.engine&&te.engine.whisper_cpp){const de=te.engine.whisper_cpp.model_size;te.engine.backend!=="moonshine"&&O("check_model_downloaded",{modelSize:de}).then(async A=>{if(!A){f(u,"engine");try{const{getCurrentWindow:T}=await Qo(async()=>{const{getCurrentWindow:Se}=await Promise.resolve().then(()=>bv);return{getCurrentWindow:Se}},void 0),Z=T();await Z.show(),await Z.setFocus()}catch(T){console.error("Failed to programmatically show settings window on startup:",T)}}}).catch(A=>{console.error("Failed to check model download status on startup:",A)})}P?P():setTimeout(()=>P(),0)}})});var x=Pd(),y=o(x),C=o(y),k=o(C),S=r(C,2);ht(S,21,()=>d,ft,(P,Y)=>{var te=Ed();let de;var A=o(te),T=o(A),Z=r(A,2),Se=o(Z),ut=r(Z,2);{var zt=qt=>{var _s=Td();g(qt,_s)};U(ut,qt=>{a(u)===a(Y).id&&qt(zt)})}G(()=>{de=ye(te,1,"nav-btn svelte-myrvk6",null,de,{active:a(u)===a(Y).id}),X(T,a(Y).icon),X(Se,a(Y).label)}),K("click",te,()=>f(u,a(Y).id,!0)),g(P,te)});var D=r(S,2),V=o(D);let $;var F=o(V),b=o(F),L=r(o(b),2),H=o(L),se=r(b,2),oe=o(se),ue=r(F,2);let w;var J=o(ue);{var q=P=>{var Y=Sd();g(P,Y)},N=P=>{var Y=Ad();g(P,Y)};U(J,P=>{n().recording?P(q):P(N,-1)})}var M=r(y,2),j=o(M),z=o(j);{var I=P=>{fc(P,{get cfg(){return Zs(),e()},set cfg(Y){Js($t,Y)}})},Q=P=>{Mc(P,{get cfg(){return Zs(),e()},set cfg(Y){Js($t,Y)}})},ce=P=>{Pu(P,{})},ie=P=>{Bu(P,{})},W=P=>{yc(P,{get cfg(){return Zs(),e()},set cfg(Y){Js($t,Y)}})},ee=P=>{Lc(P,{get cfg(){return Zs(),e()},set cfg(Y){Js($t,Y)}})},ae=P=>{ld(P,{get cfg(){return Zs(),e()},set cfg(Y){Js($t,Y)}})},ve=P=>{md(P,{get cfg(){return Zs(),e()},set cfg(Y){Js($t,Y)}})},re=P=>{hd(P,{get cfg(){return Zs(),e()},set cfg(Y){Js($t,Y)}})},ne=P=>{kd(P,{})};U(z,P=>{a(u)==="general"?P(I):a(u)==="engine"?P(Q,1):a(u)==="hotkeys"?P(ce,2):a(u)==="targets"?P(ie,3):a(u)==="visual"?P(W,4):a(u)==="audio"?P(ee,5):a(u)==="tts"?P(ae,6):a(u)==="features"?P(ve,7):a(u)==="openai"?P(re,8):a(u)==="about"&&P(ne,9)})}sl(j,P=>f(v,P),()=>a(v));var pe=r(j,2);{var Ie=P=>{var Y=Cd(),te=r(o(Y),2);K("click",te,p),g(P,Y)};U(pe,P=>{i()&&P(Ie)})}G(()=>{var P;_t(k,"src",ec),$=ye(V,1,"status-panel svelte-myrvk6",null,$,{recording:n().recording,speaking:n().speaking}),X(H,n().recording?"Recording":n().speaking?"Speaking":"Idle"),X(oe,`${(P=n().word_count)!=null?P:""} words`),w=ye(ue,1,"btn-record svelte-myrvk6",null,w,{active:n().recording})}),K("click",ue,_),g(s,x),Ye(),c()}Wt(["click"]);var Od=E(""),Id=E('
'),Dd=E('
VOXCTRL VOICE CARD
TARGET •••• VOX
');function Ld(s,t){$e(t,!0);const e=()=>kt(Et,"$status",n),[n,i]=hs();let l=qe(t,"recording",3,!1);qe(t,"speaking",3,!1);let c=qe(t,"active",3,!0);const u=20,d=6;let p=B(Be(Array(u).fill(0))),_=null,h,v=0,x=0;const y=he(()=>e().audio_ready!==!1),C=he(()=>e().active_target_label||"Focused Window");rt(()=>{gt("audio-level",z=>{v=Math.min(1,z.payload*100)}).then(z=>{_=z});let N=0;const M=new Float32Array(u);function j(){N+=.016,x+=(v-x)*.35,v*=.86;for(let z=0;zM[z]?I:M[z]*.86}f(p,Array.from(M),!0),h=requestAnimationFrame(j)}return h=requestAnimationFrame(j),()=>{_&&_(),cancelAnimationFrame(h)}});function k(N){return N===0?"red":N<=2?"amber":"green"}var S=Dd();let D;var V=o(S);let $;var F=r(o(V),8),b=r(o(F),2);{var L=N=>{var M=Ee("PROC");g(N,M)},H=N=>{var M=Ee("INIT");g(N,M)},se=N=>{var M=Ee("REC");g(N,M)};U(b,N=>{e().processing?N(L):l()&&!a(y)?N(H,1):N(se,-1)})}var oe=r(F,2);ht(oe,21,()=>a(p),ft,(N,M)=>{var j=Id();ht(j,21,()=>Array(d),ft,(z,I,Q)=>{var ce=Od();let ie;G(W=>ie=ye(ce,1,`dot ${W!=null?W:""}`,"svelte-1pt4ba2",ie,{lit:d-Q<=a(M)*d}),[()=>k(Q)]),g(z,ce)}),g(N,j)});var ue=r(oe,4),w=o(ue);{var J=N=>{var M=Ee("Reading the card…");g(N,M)},q=N=>{var M=Ee();G(()=>X(M,a(C))),g(N,M)};U(w,N=>{e().processing?N(J):N(q,-1)})}G(()=>{D=ye(S,1,"card-scene svelte-1pt4ba2",null,D,{on:c()}),$=ye(V,1,"card svelte-1pt4ba2",null,$,{processing:e().processing,initializing:l()&&!a(y)})}),g(s,S),Ye(),i()}var Nd=E('
'),Rd=E('
WAVEFORM // OSC-01 TGT ▸
');function Fd(s,t){$e(t,!0);const e=()=>kt(Et,"$status",n),[n,i]=hs();let l=qe(t,"recording",3,!1),c=qe(t,"active",3,!0);const u=126,d=500,p=78;let _=B(""),h=null,v,x=0,y=0;const C=he(()=>e().audio_ready!==!1),k=he(()=>e().active_target_label||"Focused Window");rt(()=>{gt("audio-level",ce=>{x=Math.min(1,ce.payload*100)}).then(ce=>{h=ce});const z=new Float32Array(u);let I=0;function Q(){I+=.016,y+=(x-y)*.35,x*=.86;let ce=0;if(e().processing)ce=.55*Math.sin(I*9)*(.6+.4*Math.sin(I*1.7));else if(l()&&e().audio_ready===!1)ce=.05*(Math.random()*2-1);else if(l()){const W=Math.random()*2-1;ce=Math.min(1,y*1.5)*(.45*Math.sin(I*24)+.55*W)}z.copyWithin(0,1),z[u-1]=ce;let ie="";for(let W=0;W{h&&h(),cancelAnimationFrame(v)}});var S=Rd();let D;var V=o(S),$=o(V),F=r(o($),4),b=o(F);{var L=z=>{var I=Ee("· TRANSCRIBING");g(z,I)},H=z=>{var I=Ee("· CALIBRATING");g(z,I)},se=z=>{var I=Ee("· LIVE TRACE");g(z,I)};U(b,z=>{e().processing?z(L):l()&&!a(C)?z(H,1):z(se,-1)})}var oe=r(F,4),ue=r(o(oe),2),w=o(ue),J=r($,2),q=r(o(J),6);ht(q,16,()=>[1,2,3,4],ft,(z,I)=>{var Q=Nd();G(()=>$s(Q,`left: ${I*20}%`)),g(z,Q)});var N=r(q,2);_t(N,"viewBox","0 0 500 78");var M=o(N),j=r(M);G(()=>{D=ye(S,1,"scope svelte-xjziu1",null,D,{on:c(),processing:e().processing,initializing:l()&&!a(C)}),X(w,a(k)),_t(M,"d",a(_)),_t(j,"d",a(_))}),g(s,S),Ye(),i()}var Wd=E('
');function zd(s,t){$e(t,!0);const e=()=>kt(Et,"$status",n),[n,i]=hs();let l=qe(t,"recording",3,!1),c=qe(t,"active",3,!0),u=B(0),d=null,p,_=0,h=0;const v=he(()=>e().audio_ready!==!1),x=he(()=>e().active_target_label||"Focused Window");rt(()=>{gt("audio-level",J=>{_=Math.min(1,J.payload*100)}).then(J=>{d=J});function w(){h+=(_-h)*.35,_*=.86,f(u,h,!0),p=requestAnimationFrame(w)}return p=requestAnimationFrame(w),()=>{d&&d(),cancelAnimationFrame(p)}});var y=Wd();let C;var k=r(o(y),2),S=r(o(k),2),D=o(S),V=o(D);{var $=w=>{var J=Ee("PULSE // ANALYZING");g(w,J)},F=w=>{var J=Ee("PULSE // ACQUIRING");g(w,J)},b=w=>{var J=Ee("PULSE // TARGET LOCK");g(w,J)};U(V,w=>{e().processing?w($):l()&&!a(v)?w(F,1):w(b,-1)})}var L=r(D,2),H=o(L);{var se=w=>{var J=Ee("Decoding transmission…");g(w,J)},oe=w=>{var J=Ee("Connecting mic…");g(w,J)},ue=w=>{var J=Ee();G(()=>X(J,a(x))),g(w,J)};U(H,w=>{e().processing?w(se):l()&&!a(v)?w(oe,1):w(ue,-1)})}G(()=>{var w;C=ye(y,1,"radar svelte-13tl5wx",null,C,{on:c(),processing:e().processing,initializing:l()&&!a(v)}),$s(y,`--lvl: ${(w=a(u))!=null?w:""}`)}),g(s,y),Ye(),i()}var qd=E('
'),Vd=E('
OCEAN WAVE
');function Bd(s,t){$e(t,!0);const e=()=>kt(Et,"$status",n),[n,i]=hs();let l=qe(t,"recording",3,!1);qe(t,"speaking",3,!1);let c=qe(t,"active",3,!0);const u=380,d=90;let p=B(""),_=B(""),h=B(""),v=B(60),x=null,y,C=0,k=0;const S=he(()=>e().audio_ready!==!1),D=he(()=>e().active_target_label||"Focused Window");function V(W,ee,ae,ve){let re=`M 0 ${d} L 0 ${ve.toFixed(1)}`;for(let ne=0;ne<=u;ne+=8){const pe=ve+Math.sin(ne*ee+ae)*W;re+=` L ${ne} ${pe.toFixed(1)}`}return re+` L ${u} ${d} Z`}rt(()=>{gt("audio-level",ae=>{C=Math.min(1,ae.payload*100)}).then(ae=>{x=ae});let W=0;function ee(){W+=.016,k+=(C-k)*.35,C*=.86;const ae=k,ve=e().processing?4+2.5*Math.sin(W*1.6):0,re=64-ae*20-ve,ne=56-ae*24-ve*1.2,pe=47-ae*28-ve*1.4,Ie=(e().processing?5:2.5)+ae*14,P=(e().processing?6:2)+ae*18,Y=(e().processing?7:1.5)+ae*22;f(p,V(Ie,.014,W*2.1,re),!0),f(_,V(P,.022,-W*3,ne),!0),f(h,V(Y,.018,W*3.9,pe),!0),f(v,38+pe-21+Math.sin(W*2.2)*2.5),y=requestAnimationFrame(ee)}return y=requestAnimationFrame(ee),()=>{x&&x(),cancelAnimationFrame(y)}});var $=Vd();let F;var b=r(o($),4),L=o(b);{var H=W=>{var ee=Ee("deep current — processing");g(W,ee)},se=W=>{var ee=Ee("low tide — preparing");g(W,ee)},oe=W=>{var ee=Ee("high tide — listening");g(W,ee)};U(L,W=>{e().processing?W(H):l()&&!a(S)?W(se,1):W(oe,-1)})}var ue=r(b,2),w=o(ue);_t(w,"viewBox","0 0 380 90");var J=o(w),q=r(J),N=r(q),M=r(ue,2);ht(M,16,()=>[0,1,2],ft,(W,ee)=>{var ae=qd();G(()=>$s(ae,`left: ${64+ee*112}px; animation-delay: ${ee*1.4}s;`)),g(W,ae)});var j=r(M,2),z=r(o(j),2),I=o(z);{var Q=W=>{var ee=Ee("Sounding the depths…");g(W,ee)},ce=W=>{var ee=Ee("Casting off…");g(W,ee)},ie=W=>{var ee=Ee();G(()=>X(ee,a(D))),g(W,ee)};U(I,W=>{e().processing?W(Q):l()&&!a(S)?W(ce,1):W(ie,-1)})}G(()=>{var W;F=ye($,1,"ocean svelte-1orgnnz",null,F,{on:c(),processing:e().processing}),_t(J,"d",a(p)),_t(q,"d",a(_)),_t(N,"d",a(h)),$s(j,`top: ${(W=a(v))!=null?W:""}px;`)}),g(s,$),Ye(),i()}var Ud=E("
"),jd=E('
');function Hd(s,t){$e(t,!0);const e=()=>kt(Et,"$status",n),[n,i]=hs();let l=qe(t,"recording",3,!1),c=qe(t,"active",3,!0);const u=5,d=8,p=52;let _=B(Be(Array(u).fill(d))),h=null,v,x=0,y=0;const C=he(()=>e().audio_ready!==!1),k=he(()=>e().active_target_label||"Focused Window");function S(N,M,j,z,I,Q,ce,ie){const W=(M-1)/2,ee=1-Math.abs(N-W)/(W+1)*.4;let ae;if(Q)ae=(Math.sin(z*4-N*.85)*.5+.5)*ee;else if(I&&!ce)ae=0;else if(I){const ve=Math.sin(z*3-N*.8);ae=Math.min(1,Math.max(0,j*ee*(.9+.1*ve)*(.85+.3*ie)))}else ae=0;return d+(p-d)*ae}rt(()=>{gt("audio-level",j=>{x=Math.min(1,j.payload*100)}).then(j=>{h=j});let N=0;function M(){N+=.016,y+=(x-y)*.35,x*=.86;const j=e().audio_ready!==!1,z=new Array(u);for(let I=0;I{h&&h(),cancelAnimationFrame(v)}});var D=jd();let V;var $=o(D),F=o($);let b;var L=r(F,2),H=o(L);{var se=N=>{var M=Ee("PROCESSING");g(N,M)},oe=N=>{var M=Ee("STANDBY");g(N,M)},ue=N=>{var M=Ee("LISTENING");g(N,M)};U(H,N=>{e().processing?N(se):l()&&!a(C)?N(oe,1):N(ue,-1)})}var w=r($,2);ht(w,21,()=>a(_),ft,(N,M)=>{var j=Ud();let z;G(()=>{var I;z=ye(j,1,"bar svelte-12wa5lj",null,z,{dim:l()&&!a(C),processing:e().processing}),$s(j,`height: ${(I=a(M))!=null?I:""}px`)}),g(N,j)});var J=r(w,4),q=o(J);G(()=>{V=ye(D,1,"mono svelte-12wa5lj",null,V,{on:c()}),b=ye(F,1,"dot svelte-12wa5lj",null,b,{lit:!e().processing&&!(l()&&!a(C)),processing:e().processing,standby:l()&&!a(C)}),X(q,a(k))}),g(s,D),Ye(),i()}var Kd=E('
'),$d=E('
SPECTRUM // EQ-16 OUT ▸
');function Yd(s,t){$e(t,!0);const e=()=>kt(Et,"$status",n),[n,i]=hs();let l=qe(t,"recording",3,!1),c=qe(t,"active",3,!0);const u=16,d=6,p=96;let _=B(Be(Array(u).fill(d))),h=null,v,x=0,y=0;const C=he(()=>e().audio_ready!==!1),k=he(()=>e().active_target_label||"Focused Window");function S(M,j,z,I,Q,ce,ie,W){const ee=M/(j-1);let ae;if(ce)ae=Math.pow(Math.sin(I*2.4-ee*6)*.5+.5,1.5);else if(Q&&!ie)ae=W*.06;else if(Q){const ve=2+ee*9,re=M*.7,ne=Math.sin(I*ve+re)*.5+.5,pe=1-ee*.35;ae=Math.min(1,Math.max(0,z*pe*(.35+.65*ne)*(.7+.6*W)))}else ae=0;return d+(p-d)*ae}rt(()=>{gt("audio-level",z=>{x=Math.min(1,z.payload*100)}).then(z=>{h=z});let M=0;function j(){M+=.016,y+=(x-y)*.35,x*=.86;const z=e().audio_ready!==!1,I=new Array(u);for(let Q=0;Q{h&&h(),cancelAnimationFrame(v)}});var D=$d();let V;var $=o(D),F=o($);let b;var L=r(F,4),H=o(L);{var se=M=>{var j=Ee("· ANALYZING");g(M,j)},oe=M=>{var j=Ee("· WARMING UP");g(M,j)},ue=M=>{var j=Ee("· LIVE");g(M,j)};U(H,M=>{e().processing?M(se):l()&&!a(C)?M(oe,1):M(ue,-1)})}var w=r(L,4),J=r(o(w),2),q=o(J),N=r($,4);ht(N,21,()=>a(_),ft,(M,j)=>{var z=Kd();G(()=>{var I;return $s(z,`height: ${(I=a(j))!=null?I:""}px; opacity: ${.45+.55*(a(j)/p)}`)}),g(M,z)}),G(()=>{V=ye(D,1,"spectrum svelte-194vixl",null,V,{on:c()}),b=ye(F,1,"led svelte-194vixl",null,b,{processing:e().processing,standby:l()&&!a(C)}),X(q,a(k))}),g(s,D),Ye(),i()}var Gd=E('
VOXCTRL — /dev/mic0
');function Jd(s,t){$e(t,!0);const e=()=>kt(Et,"$status",n),[n,i]=hs();let l=qe(t,"recording",3,!1),c=qe(t,"active",3,!0);const u=20;let d=B(Be("·".repeat(u))),p=B(!1),_=null,h,v=0,x=0;const y=he(()=>e().audio_ready!==!1),C=he(()=>e().active_target_label||"Focused Window");function k(I,Q,ce,ie,W){const ee=u;if(ie){const ae=2*ee,ve=Math.floor(Q*10)%ae,re=vepe===re?"█":"·").join("")}else{if(ce&&!W)return Array.from({length:ee},(ae,ve)=>ve%4===0?"·":" ").join("");if(ce){const ae=Math.round(Math.min(1,Math.max(0,I))*ee);return Array.from({length:ee},(ve,re)=>re{gt("audio-level",ce=>{v=Math.min(1,ce.payload*100)}).then(ce=>{_=ce});let I=0;function Q(){I+=.016,x+=(v-x)*.35,v*=.86;const ce=e().audio_ready!==!1;f(d,k(x,I,l(),e().processing,ce),!0),f(p,Math.sin(I*5.5)>0),h=requestAnimationFrame(Q)}return h=requestAnimationFrame(Q),()=>{_&&_(),cancelAnimationFrame(h)}});var S=Gd();let D;var V=r(o(S),2),$=o(V),F=o($),b=r($,2);let L;var H=o(b);{var se=I=>{var Q=Ee("[PROC]");g(I,Q)},oe=I=>{var Q=Ee("[INIT]");g(I,Q)},ue=I=>{var Q=Ee("[REC ]");g(I,Q)};U(H,I=>{e().processing?I(se):l()&&!a(y)?I(oe,1):I(ue,-1)})}var w=r(H),J=r(b,2),q=o(J);{var N=I=>{var Q=Ee("transcribing audio stream");g(I,Q)},M=I=>{var Q=Ee("connecting input device");g(I,Q)},j=I=>{var Q=Ee("streaming to output");g(I,Q)};U(q,I=>{e().processing?I(N):l()&&!a(y)?I(M,1):I(j,-1)})}var z=r(q,1,!0);G(()=>{var I,Q;D=ye(S,1,"terminal svelte-pvtvge",null,D,{on:c()}),X(F,`$ voxctrl listen --target "${(I=a(C))!=null?I:""}"`),L=ye(b,1,"line2 svelte-pvtvge",null,L,{processing:e().processing,standby:l()&&!a(y)}),X(w,` ${(Q=a(d))!=null?Q:""}`),X(z,a(p)?"_":" ")}),g(s,S),Ye(),i()}var Zd=E('
VU
-20
0
+3
');function Xd(s,t){$e(t,!0);const e=()=>kt(Et,"$status",n),[n,i]=hs();let l=qe(t,"recording",3,!1),c=qe(t,"active",3,!0);const u=144,d=70,p=58,_=-.95,h=.95,v=.016;let x=B(Be(F(_))),y=null,C,k=0,S=0;const D=he(()=>e().audio_ready!==!1),V=he(()=>e().active_target_label||"Focused Window");function $(ie){return _+Math.min(1,Math.max(0,ie))*(h-_)}function F(ie){const W=u+Math.sin(ie)*p,ee=d-Math.cos(ie)*p;return`M ${u} ${d} L ${W.toFixed(1)} ${ee.toFixed(1)}`}function b(ie,W,ee){const re=256*(W-ie.x)-24.96*ie.v;ie.v+=re*ee,ie.x+=ie.v*ee,Math.abs(ie.x-W)<.001&&Math.abs(ie.v)<.02&&(ie.x=W,ie.v=0)}rt(()=>{gt("audio-level",ae=>{k=Math.min(1,ae.payload*100)}).then(ae=>{y=ae});let ie=0;const W={x:_,v:0};function ee(){ie+=v,S+=(k-S)*.35,k*=.86;const ae=e().audio_ready!==!1;let ve;e().processing?ve=$(.3+.25*Math.abs(Math.sin(ie*2))):l()&&ae?ve=$(S):ve=_,b(W,ve,v),f(x,F(W.x),!0),C=requestAnimationFrame(ee)}return C=requestAnimationFrame(ee),()=>{y&&y(),cancelAnimationFrame(C)}});var L=Zd();let H;var se=o(L),oe=r(o(se),2),ue=o(oe);{var w=ie=>{var W=Ee("ANALOG // PROCESSING");g(ie,W)},J=ie=>{var W=Ee("ANALOG // WARMING UP");g(ie,W)},q=ie=>{var W=Ee("ANALOG // INPUT LEVEL");g(ie,W)};U(ue,ie=>{e().processing?ie(w):l()&&!a(D)?ie(J,1):ie(q,-1)})}var N=r(oe,4);let M;var j=r(se,2),z=r(o(j),20),I=o(z),Q=r(j,2),ce=o(Q);G(()=>{H=ye(L,1,"vinyl svelte-kq5b5i",null,H,{on:c()}),M=ye(N,1,"led svelte-kq5b5i",null,M,{processing:e().processing,standby:l()&&!a(D)}),_t(I,"d",a(x)),X(ce,a(V))}),g(s,L),Ye(),i()}var Qd=E("
",1),ev=E(''),tv=E('
SYSTEM RESPONDING
'),sv=E('
RECORDING
'),av=E(" ",1),nv=E('
');function iv(s,t){$e(t,!0);const e=()=>kt($t,"$config",u),n=()=>kt(Et,"$status",u),i=()=>kt(uc,"$recording",u),l=()=>kt(dc,"$speaking",u),c=()=>kt(vc,"$mcpRecording",u),[u,d]=hs();let p=B(!0),_=B(Be([])),h=he(()=>a(_).find(w=>w.name===e().ui.overlay_style));const v=he(()=>n().active_target_label||"Focused Window"),x=he(()=>n().active_target_label||"Focused Window");let y=he(()=>i()&&e().ui.show_overlay||l()&&e().tts.enabled&&e().tts.response_overlay||c()&&e().mcp.visual_feedback),C=B(!1),k=B(!1),S,D;ka(()=>(a(y)?(S&&clearTimeout(S),f(C,!0),D&&clearTimeout(D),D=setTimeout(()=>{f(k,!0)},25)):(f(k,!1),S=setTimeout(()=>{f(C,!1)},450)),()=>{S&&clearTimeout(S),D&&clearTimeout(D)}));let V=he(()=>a(h)?a(h).html.replace(/\{\{trigger\}\}/g,a(v)).replace(/\{\{target\}\}/g,a(x)):""),$=0,F=B(0),b=null,L;ka(()=>{e().ui.overlay_style,f(p,!1);const w=setTimeout(()=>{f(p,!0)},25);return()=>clearTimeout(w)}),ka(()=>{const w=document.documentElement;w.style.setProperty("--voxctrl-audio-level",String(a(F))),w.style.setProperty("--voxctrl-recording",i()?"1":"0"),w.style.setProperty("--voxctrl-processing",n().processing?"1":"0"),w.style.setProperty("--voxctrl-speaking",l()?"1":"0"),w.style.setProperty("--voxctrl-mcp-recording",c()?"1":"0"),w.style.setProperty("--voxctrl-audio-ready",n().audio_ready!==!1?"1":"0")}),rt(()=>{document.documentElement.classList.add("overlay-window"),document.body.classList.add("overlay-window"),document.documentElement.style.setProperty("background","transparent","important"),document.body.style.setProperty("background","transparent","important");const w=document.getElementById("app");w&&w.style.setProperty("background","transparent","important"),O("get_custom_overlays").then(q=>{f(_,q,!0)}).catch(q=>{console.error("Failed to load custom overlays:",q)}),gt("audio-level",q=>{$=Math.min(1,q.payload*100),window.dispatchEvent(new CustomEvent("voxctrl-audio-level",{detail:q.payload}))}).then(q=>{b=q});function J(){f(F,a(F)+($-a(F))*.42),$*=.82,a(h)&&window.dispatchEvent(new CustomEvent("voxctrl-status",{detail:{recording:i(),processing:n().processing,speaking:l(),audio_ready:n().audio_ready!==!1,active_target_label:n().active_target_label||"Focused Window",audio_level:a(F)}})),L=requestAnimationFrame(J)}return L=requestAnimationFrame(J),()=>{document.documentElement.classList.remove("overlay-window"),document.body.classList.remove("overlay-window"),b&&b(),cancelAnimationFrame(L)}});function H(w){return w.querySelectorAll("script").forEach(q=>{const N=document.createElement("script");Array.from(q.attributes).forEach(M=>{N.setAttribute(M.name,M.value)}),N.appendChild(document.createTextNode(q.innerHTML)),q.parentNode&&q.parentNode.replaceChild(N,q)}),{destroy(){window.dispatchEvent(new CustomEvent("voxctrl-cleanup"))}}}var se=nv(),oe=o(se);{var ue=w=>{var J=av(),q=Ct(J);{var N=re=>{Fd(re,{get recording(){return i()},get active(){return a(k)}})},M=re=>{zd(re,{get recording(){return i()},get active(){return a(k)}})},j=re=>{Bd(re,{get recording(){return i()},get speaking(){return l()},get active(){return a(k)}})},z=re=>{Hd(re,{get recording(){return i()},get active(){return a(k)}})},I=re=>{Yd(re,{get recording(){return i()},get active(){return a(k)}})},Q=re=>{Jd(re,{get recording(){return i()},get active(){return a(k)}})},ce=re=>{Xd(re,{get recording(){return i()},get active(){return a(k)}})},ie=re=>{var ne=Qd(),pe=Ct(ne);Ki(pe,()=>``);var Ie=r(pe,2);let P;Ki(Ie,()=>a(V),!0),ua(Ie,Y=>H==null?void 0:H(Y)),G(()=>P=ye(Ie,1,"custom-overlay-content svelte-rmqsd6",null,P,{active:a(k)})),g(re,ne)},W=re=>{Ld(re,{get recording(){return i()},get speaking(){return l()},get active(){return a(k)}})};U(q,re=>{e().ui.overlay_style==="waveform"?re(N):e().ui.overlay_style==="pulse"?re(M,1):e().ui.overlay_style==="blue_wave"?re(j,2):e().ui.overlay_style==="mono_bars"?re(z,3):e().ui.overlay_style==="spectrum"?re(I,4):e().ui.overlay_style==="terminal"?re(Q,5):e().ui.overlay_style==="vinyl"?re(ce,6):a(h)?re(ie,7):e().ui.overlay_style!=="none"&&re(W,8)})}var ee=r(q,2);{var ae=re=>{var ne=tv();let pe;var Ie=o(ne);ht(Ie,20,()=>[0,1,2,3,4],ft,(de,A)=>{var T=ev();G(()=>$s(T,`animation-delay: ${A*.13}s`)),g(de,T)});var P=r(Ie,2),Y=r(o(P),2),te=o(Y);G(()=>{var de;pe=ye(ne,1,"system-response-box speaking svelte-rmqsd6",null,pe,{on:a(k)}),X(te,`▸ ${(de=a(x))!=null?de:""}`)}),g(re,ne)},ve=re=>{var ne=sv();let pe;var Ie=r(o(ne),2),P=r(o(Ie),2),Y=o(P);G(()=>{var te;pe=ye(ne,1,"system-response-box mcp svelte-rmqsd6",null,pe,{on:a(k)}),X(Y,`▸ ${(te=a(x))!=null?te:""}`)}),g(re,ne)};U(ee,re=>{l()?re(ae):c()&&re(ve,1)})}g(w,J)};U(oe,w=>{a(C)&&a(p)&&w(ue)})}G(()=>{_t(se,"data-recording",i()),_t(se,"data-speaking",l()),_t(se,"data-processing",n().processing)}),g(s,se),Ye(),d()}var rv=E('
🚫

History Disabled

Transcript history is turned off. Enable it in Settings → General to start logging.

'),lv=E('
Retrieving transcript log...
'),ov=E('
📭

Log is Empty

Your transcribed speech sessions will appear here.

'),cv=E('

'),uv=E('
'),dv=E('

Transcript History

DICTATION LOGS FOR THIS SESSION

');function vv(s,t){$e(t,!0);const e=()=>kt($t,"$config",n),[n,i]=hs();let l=B(Be([])),c=B(Be([])),u=B(!0),d=he(()=>new Map(a(c).map(b=>[b.id,b])));async function p(){try{const b=await O("get_history");f(l,b.slice(0,100),!0)}catch(b){console.error("Failed to load history",b)}}rt(()=>{(async()=>{try{const[H,se]=await Promise.all([O("get_history"),O("get_targets")]);f(l,H.slice(0,100),!0),f(c,se,!0)}catch(H){console.error("Failed to load history or targets",H)}finally{f(u,!1)}})();let b,L;return gt("tauri://focus",()=>p()).then(H=>b=H),gt("status-tick",()=>p()).then(H=>L=H),()=>{b==null||b(),L==null||L()}});async function _(){await O("clear_history"),f(l,[],!0)}function h(b){try{const L=new Date(b);return isNaN(L.getTime())?"Unknown Time":L.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return"Unknown Time"}}function v(b){var H;return(H={inject:"Inject",clipboard:"Clipboard",exec:"Exec",pipe:"Pipe",socket:"Socket",file:"File",dbus:"DBus",http:"HTTP",webhook:"Webhook",mcp:"MCP"}[b])!=null?H:b}function x(b){return b?b.split(",").map(H=>H.trim()).filter(H=>H.length>0).map(H=>{const se=a(d).get(H);return se?`${se.label} (${v(se.delivery)})`:H==="default"?"Focused Window (Inject)":H}).join(" + "):""}var y=dv(),C=o(y),k=r(o(C),2),S=r(C,2);{var D=b=>{var L=rv();g(b,L)},V=b=>{var L=lv();g(b,L)},$=b=>{var L=ov();g(b,L)},F=b=>{var L=uv();ht(L,21,()=>a(l),ft,(H,se)=>{var oe=cv(),ue=o(oe),w=r(o(ue),2),J=o(w),q=r(w,2),N=r(ue,2),M=o(N),j=o(M),z=r(o(j)),I=r(j,2),Q=r(o(I)),ce=r(M,2),ie=r(o(ce));G((W,ee)=>{var ae;X(J,a(se).text),X(z,` ${W!=null?W:""}`),X(Q,` ${(ae=a(se).inference_ms)!=null?ae:""}ms`),X(ie,` ${ee!=null?ee:""}`)},[()=>h(a(se).timestamp),()=>x(a(se).target_id)]),K("click",q,()=>navigator.clipboard.writeText(a(se).text)),g(H,oe)}),g(b,L)};U(S,b=>{var L,H;(H=(L=e())==null?void 0:L.ui)!=null&&H.history_enabled?a(u)?b(V,1):a(l).length===0?b($,2):b(F,-1):b(D)})}K("click",k,_),g(s,y),Ye(),i()}Wt(["click"]);class Oi{constructor(...t){this.type="Logical",t.length===1?"Logical"in t[0]?(this.width=t[0].Logical.width,this.height=t[0].Logical.height):(this.width=t[0].width,this.height=t[0].height):(this.width=t[0],this.height=t[1])}toPhysical(t){return new Hs(this.width*t,this.height*t)}[ls](){return{width:this.width,height:this.height}}toJSON(){return this[ls]()}}class Hs{constructor(...t){this.type="Physical",t.length===1?"Physical"in t[0]?(this.width=t[0].Physical.width,this.height=t[0].Physical.height):(this.width=t[0].width,this.height=t[0].height):(this.width=t[0],this.height=t[1])}toLogical(t){return new Oi(this.width/t,this.height/t)}[ls](){return{width:this.width,height:this.height}}toJSON(){return this[ls]()}}class ba{constructor(t){this.size=t}toLogical(t){return this.size instanceof Oi?this.size:this.size.toLogical(t)}toPhysical(t){return this.size instanceof Hs?this.size:this.size.toPhysical(t)}[ls](){return{[`${this.size.type}`]:{width:this.size.width,height:this.size.height}}}toJSON(){return this[ls]()}}class Ii{constructor(...t){this.type="Logical",t.length===1?"Logical"in t[0]?(this.x=t[0].Logical.x,this.y=t[0].Logical.y):(this.x=t[0].x,this.y=t[0].y):(this.x=t[0],this.y=t[1])}toPhysical(t){return new ss(this.x*t,this.y*t)}[ls](){return{x:this.x,y:this.y}}toJSON(){return this[ls]()}}class ss{constructor(...t){this.type="Physical",t.length===1?"Physical"in t[0]?(this.x=t[0].Physical.x,this.y=t[0].Physical.y):(this.x=t[0].x,this.y=t[0].y):(this.x=t[0],this.y=t[1])}toLogical(t){return new Ii(this.x/t,this.y/t)}[ls](){return{x:this.x,y:this.y}}toJSON(){return this[ls]()}}class bn{constructor(t){this.position=t}toLogical(t){return this.position instanceof Ii?this.position:this.position.toLogical(t)}toPhysical(t){return this.position instanceof ss?this.position:this.position.toPhysical(t)}[ls](){return{[`${this.position.type}`]:{x:this.position.x,y:this.position.y}}}toJSON(){return this[ls]()}}var Dn;(function(s){s[s.Critical=1]="Critical",s[s.Informational=2]="Informational"})(Dn||(Dn={}));class rl{constructor(t){this._preventDefault=!1,this.event=t.event,this.id=t.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}var hi;(function(s){s.None="none",s.Normal="normal",s.Indeterminate="indeterminate",s.Paused="paused",s.Error="error"})(hi||(hi={}));function Di(){return new Li(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}async function An(){return O("plugin:window|get_all_windows").then(s=>s.map(t=>new Li(t,{skip:!0})))}const Zn=["tauri://created","tauri://error"];class Li{constructor(t,e={}){var n;this.label=t,this.listeners=Object.create(null),e!=null&&e.skip||O("plugin:window|create",{options:{...e,parent:typeof e.parent=="string"?e.parent:(n=e.parent)===null||n===void 0?void 0:n.label,label:t}}).then(async()=>this.emit("tauri://created")).catch(async i=>this.emit("tauri://error",i))}static async getByLabel(t){var e;return(e=(await An()).find(n=>n.label===t))!==null&&e!==void 0?e:null}static getCurrent(){return Di()}static async getAll(){return An()}static async getFocusedWindow(){for(const t of await An())if(await t.isFocused())return t;return null}async listen(t,e){return this._handleTauriEvent(t,e)?()=>{const n=this.listeners[t];n.splice(n.indexOf(e),1)}:gt(t,e,{target:{kind:"Window",label:this.label}})}async once(t,e){return this._handleTauriEvent(t,e)?()=>{const n=this.listeners[t];n.splice(n.indexOf(e),1)}:ic(t,e,{target:{kind:"Window",label:this.label}})}async emit(t,e){if(Zn.includes(t)){for(const n of this.listeners[t]||[])n({event:t,id:-1,payload:e});return}return rc(t,e)}async emitTo(t,e,n){if(Zn.includes(e)){for(const i of this.listeners[e]||[])i({event:e,id:-1,payload:n});return}return lc(t,e,n)}_handleTauriEvent(t,e){return Zn.includes(t)?(t in this.listeners?this.listeners[t].push(e):this.listeners[t]=[e],!0):!1}async scaleFactor(){return O("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return O("plugin:window|inner_position",{label:this.label}).then(t=>new ss(t))}async outerPosition(){return O("plugin:window|outer_position",{label:this.label}).then(t=>new ss(t))}async innerSize(){return O("plugin:window|inner_size",{label:this.label}).then(t=>new Hs(t))}async outerSize(){return O("plugin:window|outer_size",{label:this.label}).then(t=>new Hs(t))}async isFullscreen(){return O("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return O("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return O("plugin:window|is_maximized",{label:this.label})}async isFocused(){return O("plugin:window|is_focused",{label:this.label})}async isDecorated(){return O("plugin:window|is_decorated",{label:this.label})}async isResizable(){return O("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return O("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return O("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return O("plugin:window|is_closable",{label:this.label})}async isVisible(){return O("plugin:window|is_visible",{label:this.label})}async title(){return O("plugin:window|title",{label:this.label})}async theme(){return O("plugin:window|theme",{label:this.label})}async isAlwaysOnTop(){return O("plugin:window|is_always_on_top",{label:this.label})}async activityName(){return O("plugin:window|activity_name",{label:this.label})}async sceneIdentifier(){return O("plugin:window|scene_identifier",{label:this.label})}async center(){return O("plugin:window|center",{label:this.label})}async requestUserAttention(t){let e=null;return t&&(t===Dn.Critical?e={type:"Critical"}:e={type:"Informational"}),O("plugin:window|request_user_attention",{label:this.label,value:e})}async setResizable(t){return O("plugin:window|set_resizable",{label:this.label,value:t})}async setEnabled(t){return O("plugin:window|set_enabled",{label:this.label,value:t})}async isEnabled(){return O("plugin:window|is_enabled",{label:this.label})}async setMaximizable(t){return O("plugin:window|set_maximizable",{label:this.label,value:t})}async setMinimizable(t){return O("plugin:window|set_minimizable",{label:this.label,value:t})}async setClosable(t){return O("plugin:window|set_closable",{label:this.label,value:t})}async setTitle(t){return O("plugin:window|set_title",{label:this.label,value:t})}async maximize(){return O("plugin:window|maximize",{label:this.label})}async unmaximize(){return O("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return O("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return O("plugin:window|minimize",{label:this.label})}async unminimize(){return O("plugin:window|unminimize",{label:this.label})}async show(){return O("plugin:window|show",{label:this.label})}async hide(){return O("plugin:window|hide",{label:this.label})}async close(){return O("plugin:window|close",{label:this.label})}async destroy(){return O("plugin:window|destroy",{label:this.label})}async setDecorations(t){return O("plugin:window|set_decorations",{label:this.label,value:t})}async setShadow(t){return O("plugin:window|set_shadow",{label:this.label,value:t})}async setEffects(t){return O("plugin:window|set_effects",{label:this.label,value:t})}async clearEffects(){return O("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(t){return O("plugin:window|set_always_on_top",{label:this.label,value:t})}async setAlwaysOnBottom(t){return O("plugin:window|set_always_on_bottom",{label:this.label,value:t})}async setContentProtected(t){return O("plugin:window|set_content_protected",{label:this.label,value:t})}async setSize(t){return O("plugin:window|set_size",{label:this.label,value:t instanceof ba?t:new ba(t)})}async setMinSize(t){return O("plugin:window|set_min_size",{label:this.label,value:t instanceof ba?t:t?new ba(t):null})}async setMaxSize(t){return O("plugin:window|set_max_size",{label:this.label,value:t instanceof ba?t:t?new ba(t):null})}async setSizeConstraints(t){function e(n){return n?{Logical:n}:null}return O("plugin:window|set_size_constraints",{label:this.label,value:{minWidth:e(t==null?void 0:t.minWidth),minHeight:e(t==null?void 0:t.minHeight),maxWidth:e(t==null?void 0:t.maxWidth),maxHeight:e(t==null?void 0:t.maxHeight)}})}async setPosition(t){return O("plugin:window|set_position",{label:this.label,value:t instanceof bn?t:new bn(t)})}async setFullscreen(t){return O("plugin:window|set_fullscreen",{label:this.label,value:t})}async setSimpleFullscreen(t){return O("plugin:window|set_simple_fullscreen",{label:this.label,value:t})}async setFocus(){return O("plugin:window|set_focus",{label:this.label})}async setFocusable(t){return O("plugin:window|set_focusable",{label:this.label,value:t})}async setIcon(t){return O("plugin:window|set_icon",{label:this.label,value:In(t)})}async setSkipTaskbar(t){return O("plugin:window|set_skip_taskbar",{label:this.label,value:t})}async setCursorGrab(t){return O("plugin:window|set_cursor_grab",{label:this.label,value:t})}async setCursorVisible(t){return O("plugin:window|set_cursor_visible",{label:this.label,value:t})}async setCursorIcon(t){return O("plugin:window|set_cursor_icon",{label:this.label,value:t})}async setBackgroundColor(t){return O("plugin:window|set_background_color",{color:t})}async setCursorPosition(t){return O("plugin:window|set_cursor_position",{label:this.label,value:t instanceof bn?t:new bn(t)})}async setIgnoreCursorEvents(t){return O("plugin:window|set_ignore_cursor_events",{label:this.label,value:t})}async startDragging(){return O("plugin:window|start_dragging",{label:this.label})}async startResizeDragging(t){return O("plugin:window|start_resize_dragging",{label:this.label,value:t})}async setBadgeCount(t){return O("plugin:window|set_badge_count",{label:this.label,value:t})}async setBadgeLabel(t){return O("plugin:window|set_badge_label",{label:this.label,value:t})}async setOverlayIcon(t){return O("plugin:window|set_overlay_icon",{label:this.label,value:t?In(t):void 0})}async setProgressBar(t){return O("plugin:window|set_progress_bar",{label:this.label,value:t})}async setVisibleOnAllWorkspaces(t){return O("plugin:window|set_visible_on_all_workspaces",{label:this.label,value:t})}async setTitleBarStyle(t){return O("plugin:window|set_title_bar_style",{label:this.label,value:t})}async setTheme(t){return O("plugin:window|set_theme",{label:this.label,value:t})}async onResized(t){return this.listen(Ut.WINDOW_RESIZED,e=>{e.payload=new Hs(e.payload),t(e)})}async onMoved(t){return this.listen(Ut.WINDOW_MOVED,e=>{e.payload=new ss(e.payload),t(e)})}async onCloseRequested(t){return this.listen(Ut.WINDOW_CLOSE_REQUESTED,async e=>{const n=new rl(e);await t(n),n.isPreventDefault()||await this.destroy()})}async onDragDropEvent(t){const e=await this.listen(Ut.DRAG_ENTER,c=>{t({...c,payload:{type:"enter",paths:c.payload.paths,position:new ss(c.payload.position)}})}),n=await this.listen(Ut.DRAG_OVER,c=>{t({...c,payload:{type:"over",position:new ss(c.payload.position)}})}),i=await this.listen(Ut.DRAG_DROP,c=>{t({...c,payload:{type:"drop",paths:c.payload.paths,position:new ss(c.payload.position)}})}),l=await this.listen(Ut.DRAG_LEAVE,c=>{t({...c,payload:{type:"leave"}})});return()=>{e(),i(),n(),l()}}async onFocusChanged(t){const e=await this.listen(Ut.WINDOW_FOCUS,i=>{t({...i,payload:!0})}),n=await this.listen(Ut.WINDOW_BLUR,i=>{t({...i,payload:!1})});return()=>{e(),n()}}async onScaleChanged(t){return this.listen(Ut.WINDOW_SCALE_FACTOR_CHANGED,t)}async onThemeChanged(t){return this.listen(Ut.WINDOW_THEME_CHANGED,t)}}var Zi;(function(s){s.Disabled="disabled",s.Throttle="throttle",s.Suspend="suspend"})(Zi||(Zi={}));var Xi;(function(s){s.Default="default",s.FluentOverlay="fluentOverlay"})(Xi||(Xi={}));var _i;(function(s){s.AppearanceBased="appearanceBased",s.Light="light",s.Dark="dark",s.MediumLight="mediumLight",s.UltraDark="ultraDark",s.Titlebar="titlebar",s.Selection="selection",s.Menu="menu",s.Popover="popover",s.Sidebar="sidebar",s.HeaderView="headerView",s.Sheet="sheet",s.WindowBackground="windowBackground",s.HudWindow="hudWindow",s.FullScreenUI="fullScreenUI",s.Tooltip="tooltip",s.ContentBackground="contentBackground",s.UnderWindowBackground="underWindowBackground",s.UnderPageBackground="underPageBackground",s.Mica="mica",s.Blur="blur",s.Acrylic="acrylic",s.Tabbed="tabbed",s.TabbedDark="tabbedDark",s.TabbedLight="tabbedLight"})(_i||(_i={}));var gi;(function(s){s.FollowsWindowActiveState="followsWindowActiveState",s.Active="active",s.Inactive="inactive"})(gi||(gi={}));function Bn(s){return s===null?null:{name:s.name,scaleFactor:s.scaleFactor,position:new ss(s.position),size:new Hs(s.size),workArea:{position:new ss(s.workArea.position),size:new Hs(s.workArea.size)}}}async function pv(){return O("plugin:window|current_monitor").then(Bn)}async function fv(){return O("plugin:window|primary_monitor").then(Bn)}async function hv(s,t){return O("plugin:window|monitor_from_point",{x:s,y:t}).then(Bn)}async function _v(){return O("plugin:window|available_monitors").then(s=>s.map(Bn))}async function gv(){return O("plugin:window|cursor_position").then(s=>new ss(s))}const bv=Object.freeze(Object.defineProperty({__proto__:null,CloseRequestedEvent:rl,get Effect(){return _i},get EffectState(){return gi},LogicalPosition:Ii,LogicalSize:Oi,PhysicalPosition:ss,PhysicalSize:Hs,get ProgressBarStatus(){return hi},get UserAttentionType(){return Dn},Window:Li,availableMonitors:_v,currentMonitor:pv,cursorPosition:gv,getAllWindows:An,getCurrentWindow:Di,monitorFromPoint:hv,primaryMonitor:fv},Symbol.toStringTag,{value:"Module"}));var mv=E('
Configuring system dependencies & hotkey rules...

You may be prompted to enter your root/administrator password.

'),yv=E('Hardware hotkey rules are configured, but your active session is missing input group permissions. Please log out and log back in (or reboot) for these settings to take effect. This screen will keep appearing at startup until hotkey permissions are working.',1),wv=E('
'),xv=E(''),kv=E(''),Tv=E('
Verifying hardware permissions...
'),Ev=E('
');function Sv(s,t){$e(t,!0);let e=B(null),n=B(!1),i=B(null);rt(async()=>{try{const v=await O("check_udev_status");f(e,v,!0)}catch(v){console.error("Failed to check udev status in diagnostics window:",v)}});async function l(){try{await Di().close()}catch(v){console.error("Failed to close window natively:",v)}}async function c(){f(n,!0),f(i,null);try{const v=await O("install_system_integration");f(e,v,!0)}catch(v){console.error("Failed to install system integration:",v),f(i,v.toString(),!0)}finally{f(n,!1)}}var u=Ev(),d=o(u);{var p=v=>{var x=mv();g(v,x)},_=v=>{var x=kv(),y=o(x),C=o(y),k=r(y,2),S=o(k),D=r(k,2),V=o(D);{var $=q=>{var N=Ee("Hardware hotkey permissions are configured and working in this session. You're all set — global keyboard shortcuts are active.");g(q,N)},F=q=>{var N=yv();g(q,N)},b=q=>{var N=Ee("VoxCtrl requires global hotkey setup to capture keyboard shortcuts natively. Click below to automatically configure udev rules, input group membership, and desktop integration launcher files. This screen will keep appearing at startup until hotkey permissions are working.");g(q,N)};U(V,q=>{a(e).is_configured?q($):a(e).needs_relogin?q(F,1):q(b,-1)})}var L=r(D,2);{var H=q=>{var N=wv(),M=r(o(N),2),j=o(M);G(()=>X(j,a(i))),g(q,N)};U(L,q=>{a(i)&&q(H)})}var se=r(L,2),oe=o(se);{var ue=q=>{var N=xv();K("click",N,c),g(q,N)};U(oe,q=>{!a(e).is_configured&&!a(e).needs_relogin&&q(ue)})}var w=r(oe,2),J=o(w);G(()=>{X(C,a(e).is_configured?"✅":a(e).needs_relogin?"🔄":"⚠️"),X(S,a(e).is_configured?"Permissions Configured":a(e).needs_relogin?"Relogin Required":"Hardware Permissions Required"),X(J,a(e).is_configured||a(e).needs_relogin?"Close":"Continue Anyway")}),K("click",w,l),g(v,x)},h=v=>{var x=Tv();g(v,x)};U(d,v=>{a(n)?v(p):a(e)?v(_,1):v(h,-1)})}g(s,u),Ye()}Wt(["click"]);function Av(s){const t=window.location.pathname;function e(){return t.startsWith("/overlay")?"overlay":t.startsWith("/history")?"history":t.startsWith("/udev-warning")?"udev-warning":"settings"}const n=e();n==="overlay"&&(document.documentElement.classList.add("overlay-window"),document.body.classList.add("overlay-window"));var i=Xr(),l=Ct(i);{var c=_=>{iv(_,{})},u=_=>{vv(_,{})},d=_=>{Sv(_,{})},p=_=>{Md(_,{})};U(l,_=>{n==="overlay"?_(c):n==="history"?_(u,1):n==="udev-warning"?_(d,2):_(p,-1)})}g(s,i)}No(Av,{target:document.getElementById("app")}); diff --git a/dist/assets/index-DtLMwI2N.js b/dist/assets/index-DtLMwI2N.js new file mode 100644 index 0000000..8d5730f --- /dev/null +++ b/dist/assets/index-DtLMwI2N.js @@ -0,0 +1,25 @@ +var cl=Object.defineProperty;var Fi=s=>{throw TypeError(s)};var ul=(s,t,e)=>t in s?cl(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var Ft=(s,t,e)=>ul(s,typeof t!="symbol"?t+"":t,e),Un=(s,t,e)=>t.has(s)||Fi("Cannot "+e);var m=(s,t,e)=>(Un(s,t,"read from private field"),e?e.call(s):t.get(s)),Te=(s,t,e)=>t.has(s)?Fi("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),xe=(s,t,e,n)=>(Un(s,t,"write to private field"),n?n.call(s,e):t.set(s,e),e),Fe=(s,t,e)=>(Un(s,t,"access private method"),e);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))n(i);new MutationObserver(i=>{for(const l of i)if(l.type==="childList")for(const c of l.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&n(c)}).observe(document,{childList:!0,subtree:!0});function e(i){const l={};return i.integrity&&(l.integrity=i.integrity),i.referrerPolicy&&(l.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?l.credentials="include":i.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function n(i){if(i.ep)return;i.ep=!0;const l=e(i);fetch(i.href,l)}})();const dl="5";var Qi,er,tr;typeof window<"u"&&((tr=(er=(Qi=window.__svelte)!=null?Qi:window.__svelte={}).v)!=null?tr:er.v=new Set).add(dl);let za=!1,vl=!1;function pl(){za=!0}pl();const fl=1,hl=2,nr=4,_l=8,gl=16,bl=1,ml=2,yl=4,wl=8,xl=16,kl=1,Tl=2,ht=Symbol("uninitialized"),ir="http://www.w3.org/1999/xhtml",El="http://www.w3.org/2000/svg",Sl="http://www.w3.org/1998/Math/MathML",rr=!1;var lr=Array.isArray,Al=Array.prototype.indexOf,Oa=Array.prototype.includes,Fn=Array.from,or=Object.defineProperty,wa=Object.getOwnPropertyDescriptor,Cl=Object.getOwnPropertyDescriptors,Pl=Object.prototype,Ml=Array.prototype,cr=Object.getPrototypeOf,zi=Object.isExtensible;const Os=()=>{};function ur(s){for(var t=0;t{s=n,t=i});return{promise:e,resolve:s,reject:t}}const At=2,Da=4,zn=8,vr=1<<24,vs=16,hs=32,Ks=64,Zn=128,ns=512,_t=1024,xt=2048,ks=4096,Nt=8192,is=16384,fa=32768,Qn=1<<25,Ia=65536,Cn=1<<17,Ol=1<<18,Wa=1<<19,Dl=1<<20,xs=1<<25,da=65536,Pn=1<<21,xa=1<<22,Us=1<<23,Ka=Symbol("$state"),Il=Symbol("legacy props"),Ll=Symbol(""),mn=Symbol("attributes"),ei=Symbol("class"),ti=Symbol("style"),Ba=Symbol("text"),yn=Symbol("form reset"),Wn=new class extends Error{constructor(){super(...arguments);Ft(this,"name","StaleReactionError");Ft(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var sr;const Nl=!!((sr=globalThis.document)!=null&&sr.contentType)&&globalThis.document.contentType.includes("xml");function pr(s){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Rl(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function Fl(s,t,e){throw new Error("https://svelte.dev/e/each_key_duplicate")}function zl(s){throw new Error("https://svelte.dev/e/effect_in_teardown")}function Wl(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function ql(s){throw new Error("https://svelte.dev/e/effect_orphan")}function Vl(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function Bl(s){throw new Error("https://svelte.dev/e/props_invalid_value")}function Ul(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function jl(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function Hl(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Kl(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}function $l(){console.warn("https://svelte.dev/e/derived_inert")}function Yl(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function fr(s){return s===this.v}function hr(s,t){return s!=s?t==t:s!==t||s!==null&&typeof s=="object"||typeof s=="function"}function _r(s){return!hr(s,this.v)}let ot=null;function La(s){ot=s}function Je(s,t=!1,e){ot={p:ot,i:!1,c:null,e:null,s,x:null,r:Ce,l:za&&!t?{s:null,u:null,$:[]}:null}}function Xe(s){var t=ot,e=t.e;if(e!==null){t.e=null;for(var n of e)zr(n)}return t.i=!0,ot=t.p,{}}function ln(){return!za||ot!==null&&ot.l===null}let Zs=[];function gr(){var s=Zs;Zs=[],ur(s)}function js(s){if(Zs.length===0&&!Ya){var t=Zs;queueMicrotask(()=>{t===Zs&&gr()})}Zs.push(s)}function Gl(){for(;Zs.length>0;)gr()}function br(s){var t=Ce;if(t===null)return De.f|=Us,s;if(!(t.f&fa)&&!(t.f&Da))throw s;Vs(s,t)}function Vs(s,t){for(;t!==null;){if(t.f&Zn){if(!(t.f&fa))throw s;try{t.b.error(s);return}catch(e){s=e}}t=t.parent}throw s}const Jl=-7169;function lt(s,t){s.f=s.f&Jl|t}function mi(s){s.f&ns||s.deps===null?lt(s,_t):lt(s,ks)}function mr(s){if(s!==null)for(const t of s)!(t.f&At)||!(t.f&da)||(t.f^=da,mr(t.deps))}function yr(s,t,e){s.f&xt?t.add(s):s.f&ks&&e.add(s),mr(s.deps),lt(s,_t)}function yi(s,t,e){if(s==null)return t(void 0),e&&e(void 0),Os;const n=Ns(()=>s.subscribe(t,e));return n.unsubscribe?()=>n.unsubscribe():n}const ha=[];function Xl(s,t){return{subscribe:on(s,t).subscribe}}function on(s,t=Os){let e=null;const n=new Set;function i(u){if(hr(s,u)&&(s=u,e)){const d=!ha.length;for(const p of n)p[1](),ha.push(p,s);if(d){for(let p=0;p{n.delete(p),n.size===0&&e&&(e(),e=null)}}return{set:i,update:l,subscribe:c}}function cn(s,t,e){const n=!Array.isArray(s),i=n?[s]:s;if(!i.every(Boolean))throw new Error("derived() expects stores as input, got a falsy value");const l=t.length<2;return Xl(e,(c,u)=>{let d=!1;const p=[];let _=0,h=Os;const v=()=>{if(_)return;h();const y=t(n?p[0]:p,c,u);l?c(y):h=typeof y=="function"?y:Os},k=i.map((y,C)=>yi(y,x=>{p[C]=x,_&=~(1<{_|=1<t=e)(),t}let si=!1,Ua=!1,ai=Symbol("unmounted");function St(s,t,e){var l;const n=(l=e[t])!=null?l:e[t]={store:null,source:Mr(void 0),unsubscribe:Os};if(n.store!==s&&!(ai in e))if(n.unsubscribe(),n.store=s!=null?s:null,s==null)n.source.v=void 0,n.unsubscribe=Os;else{var i=!0;n.unsubscribe=yi(s,c=>{i?n.source.v=c:f(n.source,c)}),i=!1}return s&&ai in e?Zl(s):a(n.source)}function Js(s,t){return Ql(s,t),t}function _s(){const s={};function t(){Si(()=>{for(var e in s)s[e].unsubscribe();or(s,ai,{enumerable:!1,value:!0})})}return[s,t]}function Ql(s,t){si=!0;try{s.set(t)}finally{si=!1}}function Xs(){Ua=!0}function eo(s){var t=Ua;try{return Ua=!1,[s(),Ua]}finally{Ua=t}}let jn=null,_a=null,fe=null,$a=null,Et=null,ni=null,Ya=!1,Hn=!1,ya=null,wn=null;var Wi=0;let to=1;var Ta,zs,ta,Ea,Sa,sa,Aa,As,en,Ht,tn,Ws,ms,ys,Ca,Pa,ze,ii,ja,ri,wr,xr,xn,so,li,ma;const Ln=class Ln{constructor(){Te(this,ze);Ft(this,"id",to++);Te(this,Ta,!1);Ft(this,"linked",!0);Te(this,zs,null);Te(this,ta,null);Ft(this,"async_deriveds",new Map);Ft(this,"current",new Map);Ft(this,"previous",new Map);Ft(this,"unblocked",new Set);Te(this,Ea,new Set);Te(this,Sa,new Set);Te(this,sa,new Set);Te(this,Aa,0);Te(this,As,new Map);Te(this,en,null);Te(this,Ht,[]);Te(this,tn,[]);Te(this,Ws,new Set);Te(this,ms,new Set);Te(this,ys,new Map);Te(this,Ca,new Set);Ft(this,"is_fork",!1);Te(this,Pa,!1)}skip_effect(t){m(this,ys).has(t)||m(this,ys).set(t,{d:[],m:[]}),m(this,Ca).delete(t)}unskip_effect(t,e=n=>this.schedule(n)){var n=m(this,ys).get(t);if(n){m(this,ys).delete(t);for(var i of n.d)lt(i,xt),e(i);for(i of n.m)lt(i,ks),e(i)}m(this,Ca).add(t)}capture(t,e,n=!1){t.v!==ht&&!this.previous.has(t)&&this.previous.set(t,t.v),t.f&Us||(this.current.set(t,[e,n]),Et==null||Et.set(t,e)),this.is_fork||(t.v=e)}activate(){fe=this}deactivate(){fe=null,Et=null}flush(){try{Hn=!0,fe=this,Fe(this,ze,ja).call(this)}finally{Wi=0,ni=null,ya=null,wn=null,Hn=!1,fe=null,Et=null,ra.clear()}}discard(){for(const t of m(this,Sa))t(this);m(this,Sa).clear(),m(this,sa).clear(),Fe(this,ze,ma).call(this)}register_created_effect(t){m(this,tn).push(t)}increment(t,e){var n;if(xe(this,Aa,m(this,Aa)+1),t){let i=(n=m(this,As).get(e))!=null?n:0;m(this,As).set(e,i+1)}}decrement(t,e){var n;if(xe(this,Aa,m(this,Aa)-1),t){let i=(n=m(this,As).get(e))!=null?n:0;i===1?m(this,As).delete(e):m(this,As).set(e,i-1)}m(this,Pa)||(xe(this,Pa,!0),js(()=>{xe(this,Pa,!1),this.linked&&this.flush()}))}transfer_effects(t,e){for(const n of t)m(this,Ws).add(n);for(const n of e)m(this,ms).add(n);t.clear(),e.clear()}oncommit(t){m(this,Ea).add(t)}ondiscard(t){m(this,Sa).add(t)}on_fork_commit(t){m(this,sa).add(t)}run_fork_commit_callbacks(){for(const t of m(this,sa))t(this);m(this,sa).clear()}settled(){var t;return((t=m(this,en))!=null?t:xe(this,en,dr())).promise}static ensure(){var t;if(fe===null){const e=fe=new Ln;Fe(t=e,ze,li).call(t),!Hn&&!Ya&&js(()=>{m(e,Ta)||e.flush()})}return fe}apply(){{Et=null;return}}schedule(t){var i;if(ni=t,(i=t.b)!=null&&i.is_pending&&t.f&(Da|zn|vr)&&!(t.f&fa)){t.b.defer_effect(t);return}for(var e=t;e.parent!==null;){e=e.parent;var n=e.f;if(ya!==null&&e===Ce&&(De===null||!(De.f&At))&&!si)return;if(n&(Ks|hs)){if(!(n&_t))return;e.f^=_t}}m(this,Ht).push(e)}};Ta=new WeakMap,zs=new WeakMap,ta=new WeakMap,Ea=new WeakMap,Sa=new WeakMap,sa=new WeakMap,Aa=new WeakMap,As=new WeakMap,en=new WeakMap,Ht=new WeakMap,tn=new WeakMap,Ws=new WeakMap,ms=new WeakMap,ys=new WeakMap,Ca=new WeakMap,Pa=new WeakMap,ze=new WeakSet,ii=function(){if(this.is_fork)return!0;for(const n of m(this,As).keys()){for(var t=n,e=!1;t.parent!==null;){if(m(this,ys).has(t)){e=!0;break}t=t.parent}if(!e)return!0}return!1},ja=function(){var d,p,_,h;if(xe(this,Ta,!0),Wi++>1e3&&(Fe(this,ze,ma).call(this),no()),!Fe(this,ze,ii).call(this)){for(const v of m(this,Ws))m(this,ms).delete(v),lt(v,xt),this.schedule(v);for(const v of m(this,ms))lt(v,ks),this.schedule(v)}const t=m(this,Ht);xe(this,Ht,[]),this.apply();var e=ya=[],n=[],i=wn=[];for(const v of t)try{Fe(this,ze,ri).call(this,v,e,n)}catch(k){throw Er(v),k}if(fe=null,i.length>0){var l=Ln.ensure();for(const v of i)l.schedule(v)}if(ya=null,wn=null,Fe(this,ze,ii).call(this)){Fe(this,ze,xn).call(this,n),Fe(this,ze,xn).call(this,e);for(const[v,k]of m(this,ys))Tr(v,k);i.length>0&&Fe(d=fe,ze,ja).call(d);return}const c=Fe(this,ze,wr).call(this);if(c){Fe(p=c,ze,xr).call(p,this);return}m(this,Ws).clear(),m(this,ms).clear();for(const v of m(this,Ea))v(this);m(this,Ea).clear(),$a=this,qi(n),qi(e),$a=null,(_=m(this,en))==null||_.resolve();var u=fe;if(this.linked&&m(this,Aa)===0&&Fe(this,ze,ma).call(this),m(this,Ht).length>0){u===null&&(u=this,Fe(this,ze,li).call(this));const v=u;m(v,Ht).push(...m(this,Ht).filter(k=>!m(v,Ht).includes(k)))}u!==null&&Fe(h=u,ze,ja).call(h)},ri=function(t,e,n){t.f^=_t;for(var i=t.first;i!==null;){var l=i.f,c=(l&(hs|Ks))!==0,u=c&&(l&_t)!==0,d=u||(l&Nt)!==0||m(this,ys).has(i);if(!d&&i.fn!==null){c?i.f^=_t:l&Da?e.push(i):dn(i)&&(l&vs&&m(this,ms).add(i),Ra(i));var p=i.first;if(p!==null){i=p;continue}}for(;i!==null;){var _=i.next;if(_!==null){i=_;break}i=i.parent}}},wr=function(){for(var t=m(this,zs);t!==null;){if(!t.is_fork){for(const[e,[,n]]of this.current)if(t.current.has(e)&&!n)return t}t=m(t,zs)}return null},xr=function(t){var n;for(const[i,l]of t.current)!this.previous.has(i)&&t.previous.has(i)&&this.previous.set(i,t.previous.get(i)),this.current.set(i,l);for(const[i,l]of t.async_deriveds){const c=this.async_deriveds.get(i);c&&l.promise.then(c.resolve)}const e=i=>{var l=i.reactions;if(l!==null)for(const d of l){var c=d.f;if(c&At)e(d);else{var u=d;c&(xa|vs)&&!this.async_deriveds.has(u)&&(m(this,ms).delete(u),lt(u,xt),this.schedule(u))}}};for(const i of this.current.keys())e(i);this.oncommit(()=>t.discard()),Fe(n=t,ze,ma).call(n),fe=this,Fe(this,ze,ja).call(this)},xn=function(t){for(var e=0;e!this.current.has(v));if(i.length===0)t&&h.discard();else if(e.length>0){if(t)for(const v of m(this,Ca))h.unskip_effect(v,k=>{var y;k.f&(vs|xa)?h.schedule(k):Fe(y=h,ze,xn).call(y,[k])});h.activate();var l=new Set,c=new Map;for(var u of e)kr(u,i,l,c);c=new Map;var d=[...h.current.keys()].filter(v=>this.current.has(v)?this.current.get(v)[0]!==v.v:!0);if(d.length>0)for(const v of m(this,tn))!(v.f&(is|Nt|Cn))&&wi(v,d,c)&&(v.f&(xa|vs)?(lt(v,xt),h.schedule(v)):m(h,Ws).add(v));if(m(h,Ht).length>0){h.apply();for(var p of m(h,Ht))Fe(_=h,ze,ri).call(_,p,[],[]);xe(h,Ht,[])}h.deactivate()}}}},li=function(){_a===null?jn=_a=this:(xe(_a,ta,this),xe(this,zs,_a)),_a=this},ma=function(){var t=m(this,zs),e=m(this,ta);t===null?jn=e:xe(t,ta,e),e===null?_a=t:xe(e,zs,t),this.linked=!1};let va=Ln;function ao(s){var t=Ya;Ya=!0;try{for(var e;;){if(Gl(),fe===null)return e;fe.flush()}}finally{Ya=t}}function no(){try{Vl()}catch(s){Vs(s,ni)}}let us=null;function qi(s){var t=s.length;if(t!==0){for(var e=0;e0)){ra.clear();for(const i of us){if(i.f&(is|Nt))continue;const l=[i];let c=i.parent;for(;c!==null;)us.has(c)&&(us.delete(c),l.push(c)),c=c.parent;for(let u=l.length-1;u>=0;u--){const d=l[u];d.f&(is|Nt)||Ra(d)}}us.clear()}}us=null}}function kr(s,t,e,n){if(!e.has(s)&&(e.add(s),s.reactions!==null))for(const i of s.reactions){const l=i.f;l&At?kr(i,t,e,n):l&(xa|vs)&&!(l&xt)&&wi(i,t,n)&&(lt(i,xt),xi(i))}}function wi(s,t,e){const n=e.get(s);if(n!==void 0)return n;if(s.deps!==null)for(const i of s.deps){if(Oa.call(t,i))return!0;if(i.f&At&&wi(i,t,e))return e.set(i,!0),!0}return e.set(s,!1),!1}function xi(s){fe.schedule(s)}function Tr(s,t){if(!(s.f&hs&&s.f&_t)){s.f&xt?t.d.push(s):s.f&ks&&t.m.push(s),lt(s,_t);for(var e=s.first;e!==null;)Tr(e,t),e=e.next}}function Er(s){lt(s,_t);for(var t=s.first;t!==null;)Er(t),t=t.next}function io(s){let t=0,e=pa(0),n;return()=>{Ei()&&(a(e),Vn(()=>(t===0&&(n=Ns(()=>s(()=>Ga(e)))),t+=1,()=>{js(()=>{t-=1,t===0&&(n==null||n(),n=void 0,Ga(e))})})))}}var ro=Ia|Wa;function lo(s,t,e,n){new oo(s,t,e,n)}var Qt,bi,es,aa,zt,ts,Lt,Kt,Cs,na,qs,Ma,sn,an,Ps,Nn,ct,co,uo,vo,oi,kn,Tn,ci,ui;class oo{constructor(t,e,n,i){Te(this,ct);Ft(this,"parent");Ft(this,"is_pending",!1);Ft(this,"transform_error");Te(this,Qt);Te(this,bi,null);Te(this,es);Te(this,aa);Te(this,zt);Te(this,ts,null);Te(this,Lt,null);Te(this,Kt,null);Te(this,Cs,null);Te(this,na,0);Te(this,qs,0);Te(this,Ma,!1);Te(this,sn,new Set);Te(this,an,new Set);Te(this,Ps,null);Te(this,Nn,io(()=>(xe(this,Ps,pa(m(this,na))),()=>{xe(this,Ps,null)})));var l,c;xe(this,Qt,t),xe(this,es,e),xe(this,aa,u=>{var d=Ce;d.b=this,d.f|=Zn,n(u)}),this.parent=Ce.b,this.transform_error=(c=i!=null?i:(l=this.parent)==null?void 0:l.transform_error)!=null?c:u=>u,xe(this,zt,Ai(()=>{Fe(this,ct,oi).call(this)},ro))}defer_effect(t){yr(t,m(this,sn),m(this,an))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!m(this,es).pending}update_pending_count(t,e){Fe(this,ct,ci).call(this,t,e),xe(this,na,m(this,na)+t),!(!m(this,Ps)||m(this,Ma))&&(xe(this,Ma,!0),js(()=>{xe(this,Ma,!1),m(this,Ps)&&Na(m(this,Ps),m(this,na))}))}get_effect_pending(){return m(this,Nn).call(this),a(m(this,Ps))}error(t){if(!m(this,es).onerror&&!m(this,es).failed)throw t;fe!=null&&fe.is_fork?(m(this,ts)&&fe.skip_effect(m(this,ts)),m(this,Lt)&&fe.skip_effect(m(this,Lt)),m(this,Kt)&&fe.skip_effect(m(this,Kt)),fe.on_fork_commit(()=>{Fe(this,ct,ui).call(this,t)})):Fe(this,ct,ui).call(this,t)}}Qt=new WeakMap,bi=new WeakMap,es=new WeakMap,aa=new WeakMap,zt=new WeakMap,ts=new WeakMap,Lt=new WeakMap,Kt=new WeakMap,Cs=new WeakMap,na=new WeakMap,qs=new WeakMap,Ma=new WeakMap,sn=new WeakMap,an=new WeakMap,Ps=new WeakMap,Nn=new WeakMap,ct=new WeakSet,co=function(){try{xe(this,ts,ss(()=>m(this,aa).call(this,m(this,Qt))))}catch(t){this.error(t)}},uo=function(t){const e=m(this,es).failed;e&&xe(this,Kt,ss(()=>{e(m(this,Qt),()=>t,()=>()=>{})}))},vo=function(){const t=m(this,es).pending;t&&(this.is_pending=!0,xe(this,Lt,ss(()=>t(m(this,Qt)))),js(()=>{var e=xe(this,Cs,document.createDocumentFragment()),n=Ds();e.append(n),xe(this,ts,Fe(this,ct,Tn).call(this,()=>ss(()=>m(this,aa).call(this,n)))),m(this,qs)===0&&(m(this,Qt).before(e),xe(this,Cs,null),oa(m(this,Lt),()=>{xe(this,Lt,null)}),Fe(this,ct,kn).call(this,fe))}))},oi=function(){try{if(this.is_pending=this.has_pending_snippet(),xe(this,qs,0),xe(this,na,0),xe(this,ts,ss(()=>{m(this,aa).call(this,m(this,Qt))})),m(this,qs)>0){var t=xe(this,Cs,document.createDocumentFragment());Mi(m(this,ts),t);const e=m(this,es).pending;xe(this,Lt,ss(()=>e(m(this,Qt))))}else Fe(this,ct,kn).call(this,fe)}catch(e){this.error(e)}},kn=function(t){this.is_pending=!1,t.transfer_effects(m(this,sn),m(this,an))},Tn=function(t){var e=Ce,n=De,i=ot;Ts(m(this,zt)),ls(m(this,zt)),La(m(this,zt).ctx);try{return va.ensure(),t()}catch(l){return br(l),null}finally{Ts(e),ls(n),La(i)}},ci=function(t,e){var n;if(!this.has_pending_snippet()){this.parent&&Fe(n=this.parent,ct,ci).call(n,t,e);return}xe(this,qs,m(this,qs)+t),m(this,qs)===0&&(Fe(this,ct,kn).call(this,e),m(this,Lt)&&oa(m(this,Lt),()=>{xe(this,Lt,null)}),m(this,Cs)&&(m(this,Qt).before(m(this,Cs)),xe(this,Cs,null)))},ui=function(t){m(this,ts)&&(qt(m(this,ts)),xe(this,ts,null)),m(this,Lt)&&(qt(m(this,Lt)),xe(this,Lt,null)),m(this,Kt)&&(qt(m(this,Kt)),xe(this,Kt,null));var e=m(this,es).onerror;let n=m(this,es).failed;var i=!1,l=!1;const c=()=>{if(i){Yl();return}i=!0,l&&Kl(),m(this,Kt)!==null&&oa(m(this,Kt),()=>{xe(this,Kt,null)}),Fe(this,ct,Tn).call(this,()=>{Fe(this,ct,oi).call(this)})},u=d=>{try{l=!0,e==null||e(d,c),l=!1}catch(p){Vs(p,m(this,zt)&&m(this,zt).parent)}n&&xe(this,Kt,Fe(this,ct,Tn).call(this,()=>{try{return ss(()=>{var p=Ce;p.b=this,p.f|=Zn,n(m(this,Qt),()=>d,()=>c)})}catch(p){return Vs(p,m(this,zt).parent),null}}))};js(()=>{var d;try{d=this.transform_error(t)}catch(p){Vs(p,m(this,zt)&&m(this,zt).parent);return}d!==null&&typeof d=="object"&&typeof d.then=="function"?d.then(u,p=>Vs(p,m(this,zt)&&m(this,zt).parent)):u(d)})};function po(s,t,e,n){const i=ln()?Xa:ki;var l=s.filter(v=>!v.settled);if(e.length===0&&l.length===0){n(t.map(i));return}var c=Ce,u=fo(),d=l.length===1?l[0].promise:l.length>1?Promise.all(l.map(v=>v.promise)):null;function p(v){if(!(c.f&is)){u();try{n(v)}catch(k){Vs(k,c)}Mn()}}var _=Sr();if(e.length===0){d.then(()=>p(t.map(i))).finally(_);return}function h(){Promise.all(e.map(v=>ho(v))).then(v=>p([...t.map(i),...v])).catch(v=>Vs(v,c)).finally(_)}d?d.then(()=>{u(),h(),Mn()}):h()}function fo(){var s=Ce,t=De,e=ot,n=fe;return function(l=!0){Ts(s),ls(t),La(e),l&&!(s.f&is)&&(n==null||n.activate(),n==null||n.apply())}}function Mn(s=!0){Ts(null),ls(null),La(null),s&&(fe==null||fe.deactivate())}function Sr(){var s=Ce,t=s.b,e=fe,n=t.is_rendered();return t.update_pending_count(1,e),e.increment(n,s),()=>{t.update_pending_count(-1,e),e.decrement(n,s)}}function Xa(s){var t=At|xt;return Ce!==null&&(Ce.f|=Wa),{ctx:ot,deps:null,effects:null,equals:fr,f:t,fn:s,reactions:null,rv:0,v:ht,wv:0,parent:Ce,ac:null}}const _n=Symbol("obsolete");function ho(s,t,e){let n=Ce;n===null&&Rl();var i=void 0,l=pa(ht),c=!De,u=new Set;return Eo(()=>{var k;var d=Ce,p=dr();i=p.promise;try{Promise.resolve(s()).then(p.resolve,y=>{y!==Wn&&p.reject(y)}).finally(Mn)}catch(y){p.reject(y),Mn()}var _=fe;if(c){if(d.f&fa)var h=Sr();if(n.b.is_rendered())(k=_.async_deriveds.get(d))==null||k.reject(_n);else for(const y of u.values())y.reject(_n);u.add(p),_.async_deriveds.set(d,p)}const v=(y,C=void 0)=>{h==null||h(),u.delete(p),C!==_n&&(_.activate(),C?(l.f|=Us,Na(l,C)):(l.f&Us&&(l.f^=Us),Na(l,y)),_.deactivate())};p.promise.then(v,y=>v(null,y||"unknown"))}),Si(()=>{for(const d of u)d.reject(_n)}),new Promise(d=>{function p(_){function h(){_===i?d(l):p(i)}_.then(h,h)}p(i)})}function he(s){const t=Xa(s);return jr(t),t}function ki(s){const t=Xa(s);return t.equals=_r,t}function _o(s){var t=s.effects;if(t!==null){s.effects=null;for(var e=0;e0&&!Pr&&bo()}return t}function bo(){Pr=!1;for(const s of On){s.f&_t&<(s,ks);let t;try{t=dn(s)}catch{t=!0}t&&Ra(s)}On.clear()}function Ga(s){f(s,s.v+1)}function Or(s,t,e){var n=s.reactions;if(n!==null)for(var i=ln(),l=n.length,c=0;c{if(ca===l)return u();var d=De,p=ca;ls(null),ji(l);var _=u();return ls(d),ji(p),_};return n&&e.set("length",W(s.length)),new Proxy(s,{defineProperty(u,d,p){(!("value"in p)||p.configurable===!1||p.enumerable===!1||p.writable===!1)&&Ul();var _=e.get(d);return _===void 0?c(()=>{var h=W(p.value);return e.set(d,h),h}):f(_,p.value,!0),!0},deleteProperty(u,d){var p=e.get(d);if(p===void 0){if(d in u){const _=c(()=>W(ht));e.set(d,_),Ga(i)}}else f(p,ht),Ga(i);return!0},get(u,d,p){var k;if(d===Ka)return s;var _=e.get(d),h=d in u;if(_===void 0&&(!h||(k=wa(u,d))!=null&&k.writable)&&(_=c(()=>{var y=Ue(h?u[d]:ht),C=W(y);return C}),e.set(d,_)),_!==void 0){var v=a(_);return v===ht?void 0:v}return Reflect.get(u,d,p)},getOwnPropertyDescriptor(u,d){var p=Reflect.getOwnPropertyDescriptor(u,d);if(p&&"value"in p){var _=e.get(d);_&&(p.value=a(_))}else if(p===void 0){var h=e.get(d),v=h==null?void 0:h.v;if(h!==void 0&&v!==ht)return{enumerable:!0,configurable:!0,value:v,writable:!0}}return p},has(u,d){var v;if(d===Ka)return!0;var p=e.get(d),_=p!==void 0&&p.v!==ht||Reflect.has(u,d);if(p!==void 0||Ce!==null&&(!_||(v=wa(u,d))!=null&&v.writable)){p===void 0&&(p=c(()=>{var k=_?Ue(u[d]):ht,y=W(k);return y}),e.set(d,p));var h=a(p);if(h===ht)return!1}return _},set(u,d,p,_){var U;var h=e.get(d),v=d in u;if(n&&d==="length")for(var k=p;kW(ht)),e.set(k+"",y))}if(h===void 0)(!v||(U=wa(u,d))!=null&&U.writable)&&(h=c(()=>W(void 0)),f(h,Ue(p)),e.set(d,h));else{v=h.v!==ht;var C=c(()=>Ue(p));f(h,C)}var x=Reflect.getOwnPropertyDescriptor(u,d);if(x!=null&&x.set&&x.set.call(_,p),!v){if(n&&typeof d=="string"){var S=e.get("length"),D=Number(d);Number.isInteger(D)&&D>=S.v&&f(S,D+1)}Ga(i)}return!0},ownKeys(u){a(i);var d=Reflect.ownKeys(u).filter(h=>{var v=e.get(h);return v===void 0||v.v!==ht});for(var[p,_]of e)_.v!==ht&&!(p in u)&&d.push(p);return d},setPrototypeOf(){jl()}})}var Vi,Dr,Ir,Lr;function mo(){if(Vi===void 0){Vi=window,Dr=/Firefox/.test(navigator.userAgent);var s=Element.prototype,t=Node.prototype,e=Text.prototype;Ir=wa(t,"firstChild").get,Lr=wa(t,"nextSibling").get,zi(s)&&(s[ei]=void 0,s[mn]=null,s[ti]=void 0,s.__e=void 0),zi(e)&&(e[Ba]=void 0)}}function Ds(s=""){return document.createTextNode(s)}function Bs(s){return Ir.call(s)}function un(s){return Lr.call(s)}function o(s,t){return Bs(s)}function Ot(s,t=!1){{var e=Bs(s);return e instanceof Comment&&e.data===""?un(e):e}}function r(s,t=1,e=!1){let n=s;for(;t--;)n=un(n);return n}function yo(s){s.textContent=""}function Nr(){return!1}function Rr(s,t,e){return document.createElementNS(t!=null?t:ir,s,void 0)}let Bi=!1;function wo(){Bi||(Bi=!0,document.addEventListener("reset",s=>{Promise.resolve().then(()=>{var t;if(!s.defaultPrevented)for(const e of s.target.elements)(t=e[yn])==null||t.call(e)})},{capture:!0}))}function qn(s){var t=De,e=Ce;ls(null),Ts(null);try{return s()}finally{ls(t),Ts(e)}}function Fr(s,t,e,n=e){s.addEventListener(t,()=>qn(e));const i=s[yn];i?s[yn]=()=>{i(),n(!0)}:s[yn]=()=>n(!0),wo()}function xo(s){Ce===null&&(De===null&&ql(),Wl()),Is&&zl()}function ko(s,t){var e=t.last;e===null?t.last=t.first=s:(e.next=s,s.prev=e,t.last=s)}function Ls(s,t){var c;var e=Ce;e!==null&&e.f&Nt&&(s|=Nt);var n={ctx:ot,deps:null,nodes:null,f:s|xt|ns,first:null,fn:t,last:null,next:null,parent:e,b:e&&e.b,prev:null,teardown:null,wv:0,ac:null};fe==null||fe.register_created_effect(n);var i=n;if(s&Da)ya!==null?ya.push(n):va.ensure().schedule(n);else if(t!==null){try{Ra(n)}catch(u){throw qt(n),u}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&Wa)&&(i=i.first,s&vs&&s&Ia&&i!==null&&(i.f|=Ia))}if(i!==null&&(i.parent=e,e!==null&&ko(i,e),De!==null&&De.f&At&&!(s&Ks))){var l=De;((c=l.effects)!=null?c:l.effects=[]).push(i)}return n}function Ei(){return De!==null&&!ps}function Si(s){const t=Ls(zn,null);return lt(t,_t),t.teardown=s,t}function ka(s){var i;xo();var t=Ce.f,e=!De&&(t&hs)!==0&&(t&fa)===0;if(e){var n=ot;((i=n.e)!=null?i:n.e=[]).push(s)}else return zr(s)}function zr(s){return Ls(Da|Dl,s)}function To(s){va.ensure();const t=Ls(Ks|Wa,s);return(e={})=>new Promise(n=>{e.outro?oa(t,()=>{qt(t),n(void 0)}):(qt(t),n(void 0))})}function la(s){return Ls(Da,s)}function Eo(s){return Ls(xa|Wa,s)}function Vn(s,t=0){return Ls(zn|t,s)}function J(s,t=[],e=[],n=[]){po(n,t,e,i=>{Ls(zn,()=>s(...i.map(a)))})}function Ai(s,t=0){var e=Ls(vs|t,s);return e}function ss(s){return Ls(hs|Wa,s)}function Wr(s){var t=s.teardown;if(t!==null){const e=Is,n=De;Ui(!0),ls(null);try{t.call(null)}finally{Ui(e),ls(n)}}}function Ci(s,t=!1){var e=s.first;for(s.first=s.last=null;e!==null;){const i=e.ac;i!==null&&qn(()=>{i.abort(Wn)});var n=e.next;e.f&Ks?e.parent=null:qt(e,t),e=n}}function So(s){for(var t=s.first;t!==null;){var e=t.next;t.f&hs||qt(t),t=e}}function qt(s,t=!0){var e=!1;(t||s.f&Ol)&&s.nodes!==null&&s.nodes.end!==null&&(qr(s.nodes.start,s.nodes.end),e=!0),lt(s,Qn),Ci(s,t&&!e),Za(s,0);var n=s.nodes&&s.nodes.t;if(n!==null)for(const l of n)l.stop();Wr(s),s.f^=Qn,s.f|=is;var i=s.parent;i!==null&&i.first!==null&&Vr(s),s.next=s.prev=s.teardown=s.ctx=s.deps=s.fn=s.nodes=s.ac=s.b=null}function qr(s,t){for(;s!==null;){var e=s===t?null:un(s);s.remove(),s=e}}function Vr(s){var t=s.parent,e=s.prev,n=s.next;e!==null&&(e.next=n),n!==null&&(n.prev=e),t!==null&&(t.first===s&&(t.first=n),t.last===s&&(t.last=e))}function oa(s,t,e=!0){var n=[];Br(s,n,!0);var i=()=>{e&&qt(s),t&&t()},l=n.length;if(l>0){var c=()=>--l||i();for(var u of n)u.out(c)}else i()}function Br(s,t,e){if(!(s.f&Nt)){s.f^=Nt;var n=s.nodes&&s.nodes.t;if(n!==null)for(const u of n)(u.is_global||e)&&t.push(u);for(var i=s.first;i!==null;){var l=i.next;if(!(i.f&Ks)){var c=(i.f&Ia)!==0||(i.f&hs)!==0&&(s.f&vs)!==0;Br(i,t,c?e:!1)}i=l}}}function Pi(s){Ur(s,!0)}function Ur(s,t){if(s.f&Nt){s.f^=Nt,s.f&_t||(lt(s,xt),va.ensure().schedule(s));for(var e=s.first;e!==null;){var n=e.next,i=(e.f&Ia)!==0||(e.f&hs)!==0;Ur(e,i?t:!1),e=n}var l=s.nodes&&s.nodes.t;if(l!==null)for(const c of l)(c.is_global||t)&&c.in()}}function Mi(s,t){if(s.nodes)for(var e=s.nodes.start,n=s.nodes.end;e!==null;){var i=e===n?null:un(e);t.append(e),e=i}}let En=!1,Is=!1;function Ui(s){Is=s}let De=null,ps=!1;function ls(s){De=s}let Ce=null;function Ts(s){Ce=s}let rs=null;function jr(s){De!==null&&(rs===null?rs=[s]:rs.push(s))}let Wt=null,Ut=0,Zt=null;function Ao(s){Zt=s}let Hr=1,Qs=0,ca=Qs;function ji(s){ca=s}function Kr(){return++Hr}function dn(s){var t=s.f;if(t&xt)return!0;if(t&At&&(s.f&=~da),t&ks){for(var e=s.deps,n=e.length,i=0;is.wv)return!0}t&ns&&Et===null&<(s,_t)}return!1}function $r(s,t,e=!0){var n=s.reactions;if(n!==null&&!(rs!==null&&Oa.call(rs,s)))for(var i=0;i{s.ac.abort(Wn)}),s.ac=null);try{s.f|=Pn;var _=s.fn,h=_();s.f|=fa;var v=s.deps,k=fe==null?void 0:fe.is_fork;if(Wt!==null){var y;if(k||Za(s,Ut),v!==null&&Ut>0)for(v.length=Ut+Wt.length,y=0;ye==null?void 0:e.call(this,l))}return s.startsWith("pointer")||s.startsWith("touch")||s==="wheel"?js(()=>{t.addEventListener(s,i,n)}):t.addEventListener(s,i,n),i}function Ms(s,t,e,n,i){var l={capture:n,passive:i},c=Mo(s,t,e,l);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&Si(()=>{t.removeEventListener(s,c,l)})}function H(s,t,e){var n;((n=t[ea])!=null?n:t[ea]={})[s]=e}function Vt(s){for(var t=0;t{throw D});throw v}}finally{s[ea]=t,delete s.currentTarget,ls(_),Ts(h)}}}var ar;const Kn=((ar=globalThis==null?void 0:globalThis.window)==null?void 0:ar.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:s=>s});function Oo(s){var t;return(t=Kn==null?void 0:Kn.createHTML(s))!=null?t:s}function Do(s){var t=Rr("template");return t.innerHTML=Oo(s.replaceAll("","")),t.content}function Fa(s,t){var e=Ce;e.nodes===null&&(e.nodes={start:s,end:t,a:null,t:null})}function T(s,t){var e=(t&kl)!==0,n=(t&Tl)!==0,i,l=!s.startsWith("");return()=>{i===void 0&&(i=Do(l?s:""+s),e||(i=Bs(i)));var c=n||Dr?document.importNode(i,!0):i.cloneNode(!0);if(e){var u=Bs(c),d=c.lastChild;Fa(u,d)}else Fa(c,c);return c}}function Ee(s=""){{var t=Ds(s+"");return Fa(t,t),t}}function Zr(){var s=document.createDocumentFragment(),t=document.createComment(""),e=Ds();return s.append(t,e),Fa(t,e),s}function g(s,t){s!==null&&s.before(t)}const Io=["touchstart","touchmove"];function Lo(s){return Io.includes(s)}function ee(s,t){var n;var e=t==null?"":typeof t=="object"?`${t}`:t;e!==((n=s[Ba])!=null?n:s[Ba]=s.nodeValue)&&(s[Ba]=e,s.nodeValue=`${e}`)}function No(s,t){return Ro(s,t)}const gn=new Map;function Ro(s,{target:t,anchor:e,props:n={},events:i,context:l,intro:c=!0,transformError:u}){mo();var d=void 0,p=To(()=>{var _=e!=null?e:t.appendChild(Ds());lo(_,{pending:()=>{}},k=>{Je({});var y=ot;l&&(y.c=l),i&&(n.$$events=i),d=s(k,n)||{},Xe()},u);var h=new Set,v=k=>{for(var y=0;y{var x;for(var k of h)for(const S of[t,document]){var y=gn.get(S),C=y.get(k);--C==0?(S.removeEventListener(k,vi),y.delete(k),y.size===0&&gn.delete(S)):y.set(k,C)}di.delete(v),_!==e&&((x=_.parentNode)==null||x.removeChild(_))}});return Fo.set(d,p),d}let Fo=new WeakMap;var ds,ws,$t,ia,nn,rn,Rn;class zo{constructor(t,e=!0){Ft(this,"anchor");Te(this,ds,new Map);Te(this,ws,new Map);Te(this,$t,new Map);Te(this,ia,new Set);Te(this,nn,!0);Te(this,rn,t=>{if(m(this,ds).has(t)){var e=m(this,ds).get(t),n=m(this,ws).get(e);if(n)Pi(n),m(this,ia).delete(e);else{var i=m(this,$t).get(e);i&&(m(this,ws).set(e,i.effect),m(this,$t).delete(e),i.fragment.lastChild.remove(),this.anchor.before(i.fragment),n=i.effect)}for(const[l,c]of m(this,ds)){if(m(this,ds).delete(l),l===t)break;const u=m(this,$t).get(c);u&&(qt(u.effect),m(this,$t).delete(c))}for(const[l,c]of m(this,ws)){if(l===e||m(this,ia).has(l))continue;const u=()=>{if(Array.from(m(this,ds).values()).includes(l)){var p=document.createDocumentFragment();Mi(c,p),p.append(Ds()),m(this,$t).set(l,{effect:c,fragment:p})}else qt(c);m(this,ia).delete(l),m(this,ws).delete(l)};m(this,nn)||!n?(m(this,ia).add(l),oa(c,u,!1)):u()}}});Te(this,Rn,t=>{m(this,ds).delete(t);const e=Array.from(m(this,ds).values());for(const[n,i]of m(this,$t))e.includes(n)||(qt(i.effect),m(this,$t).delete(n))});this.anchor=t,xe(this,nn,e)}ensure(t,e){var n=fe,i=Nr();if(e&&!m(this,ws).has(t)&&!m(this,$t).has(t))if(i){var l=document.createDocumentFragment(),c=Ds();l.append(c),m(this,$t).set(t,{effect:ss(()=>e(c)),fragment:l})}else m(this,ws).set(t,ss(()=>e(this.anchor)));if(m(this,ds).set(n,t),i){for(const[u,d]of m(this,ws))u===t?n.unskip_effect(d):n.skip_effect(d);for(const[u,d]of m(this,$t))u===t?n.unskip_effect(d.effect):n.skip_effect(d.effect);n.oncommit(m(this,rn)),n.ondiscard(m(this,Rn))}else m(this,rn).call(this,n)}}ds=new WeakMap,ws=new WeakMap,$t=new WeakMap,ia=new WeakMap,nn=new WeakMap,rn=new WeakMap,Rn=new WeakMap;function ut(s){ot===null&&pr(),za&&ot.l!==null?Wo(ot).m.push(s):ka(()=>{const t=Ns(s);if(typeof t=="function")return t})}function Qr(s){ot===null&&pr(),ut(()=>()=>Ns(s))}function Wo(s){var e;var t=s.l;return(e=t.u)!=null?e:t.u={a:[],b:[],m:[]}}function B(s,t,e=!1){var n=new zo(s),i=e?Ia:0;function l(c,u){n.ensure(c,u)}Ai(()=>{var c=!1;t((u,d=0)=>{c=!0,l(d,u)}),c||l(-1,null)},i)}function gt(s,t){return t}function qo(s,t,e){var h;for(var n=[],i=t.length,l,c=t.length,u=0;u{if(l){if(l.pending.delete(v),l.done.add(v),l.pending.size===0){var k=s.outrogroups;pi(s,Fn(l.done)),k.delete(l),k.size===0&&(s.outrogroups=null)}}else c-=1},!1)}if(c===0){var d=n.length===0&&e!==null;if(d){var p=e,_=p.parentNode;yo(_),_.append(p),s.items.clear()}pi(s,t,!d)}else l={pending:new Set(t),done:new Set},((h=s.outrogroups)!=null?h:s.outrogroups=new Set).add(l)}function pi(s,t,e=!0){var n;if(s.pending.size>0){n=new Set;for(const c of s.pending.values())for(const u of c)n.add(s.items.get(u).e)}for(var i=0;i{var U=e();return lr(U)?U:U==null?[]:Fn(U)}),v,k=new Map,y=!0;function C(U){D.effect.f&is||(D.pending.delete(U),D.fallback=_,Vo(D,v,c,t,n),_!==null&&(v.length===0?_.f&xs?(_.f^=xs,Ha(_,null,c)):Pi(_):oa(_,()=>{_=null})))}function x(U){D.pending.delete(U)}var S=Ai(()=>{v=a(h);for(var U=v.length,Y=new Set,z=fe,b=Nr(),L=0;Ll(c)):(_=ss(()=>l(ga!=null?ga:ga=Ds())),_.f|=xs)),U>Y.size&&Fl(),!y)if(k.set(z,Y),b){for(const[de,w]of u)Y.has(de)||z.skip_effect(w.e);z.oncommit(C),z.ondiscard(x)}else C(z);a(h)}),D={effect:S,items:u,pending:k,outrogroups:null,fallback:_};y=!1}function Va(s){for(;s!==null&&!(s.f&hs);)s=s.next;return s}function Vo(s,t,e,n,i){var oe,de,w,X,V,N,F,se,j;var l=(n&_l)!==0,c=t.length,u=s.items,d=Va(s.effect.first),p,_=null,h,v=[],k=[],y,C,x,S;if(l)for(S=0;S0){var ae=n&nr&&c===0?e:null;if(l){for(S=0;S{var I,re;if(h!==void 0)for(x of h)(re=(I=x.nodes)==null?void 0:I.a)==null||re.apply()})}function Bo(s,t,e,n,i,l,c,u){var d=c&fl?c&gl?pa(e):Mr(e,!1,!1):null,p=c&hl?pa(i):null;return{v:d,i:p,e:ss(()=>(l(t,d!=null?d:e,p!=null?p:i,u),()=>{s.delete(n)}))}}function Ha(s,t,e){if(s.nodes)for(var n=s.nodes.start,i=s.nodes.end,l=t&&!(t.f&xs)?t.nodes.start:e;n!==null;){var c=un(n);if(l.before(n),n===i)return;n=c}}function Fs(s,t,e){t===null?s.effect.first=e:t.next=e,e===null?s.effect.last=t:e.prev=t}function Ki(s,t,e=!1,n=!1,i=!1,l=!1){var c=s,u="";if(e)var d=s;J(()=>{var k;var p=Ce;if(u!==(u=(k=t())!=null?k:"")){if(e){p.nodes=null,d.innerHTML=u,u!==""&&Fa(Bs(d),d.lastChild);return}if(p.nodes!==null&&(qr(p.nodes.start,p.nodes.end),p.nodes=null),u!==""){var _=n?El:i?Sl:void 0,h=Rr(n?"svg":i?"math":"template",_);h.innerHTML=u;var v=n||i?h:h.content;if(Fa(Bs(v),v.lastChild),n||i)for(;Bs(v);)c.before(Bs(v));else c.before(v)}}})}function ua(s,t,e){la(()=>{var n=Ns(()=>t(s,e==null?void 0:e())||{});if(n!=null&&n.destroy)return()=>n.destroy()})}function el(s){var t,e,n="";if(typeof s=="string"||typeof s=="number")n+=s;else if(typeof s=="object")if(Array.isArray(s)){var i=s.length;for(t=0;t=0;){var u=c+l;(c===0||$i.includes(n[c-1]))&&(u===n.length||$i.includes(n[u]))?n=(c===0?"":n.substring(0,c))+n.substring(u+1):c=u}}return n===""?null:n}function Ho(s,t){return s==null?null:String(s)}function ye(s,t,e,n,i,l){var c=s[ei];if(c!==e||c===void 0){var u=jo(e,n,l);u==null?s.removeAttribute("class"):s.className=u,s[ei]=e}else if(l&&i!==l)for(var d in l){var p=!!l[d];(i==null||p!==!!i[d])&&s.classList.toggle(d,p)}return l}function $s(s,t,e,n){var i=s[ti];if(i!==t){var l=Ho(t);l==null?s.removeAttribute("style"):s.style.cssText=l,s[ti]=t}return n}const Ko=Symbol("is custom element"),$o=Symbol("is html"),Yo=Nl?"progress":"PROGRESS";function Go(s,t){var e=tl(s);e.value===(e.value=t!=null?t:void 0)||s.value===t&&(t!==0||s.nodeName!==Yo)||(s.value=t!=null?t:"")}function mt(s,t,e,n){var i=tl(s);i[t]!==(i[t]=e)&&(t==="loading"&&(s[Ll]=e),e==null?s.removeAttribute(t):typeof e!="string"&&Jo(s).includes(t)?s[t]=e:s.setAttribute(t,e))}function tl(s){var t;return(t=s[mn])!=null?t:s[mn]={[Ko]:s.nodeName.includes("-"),[$o]:s.namespaceURI===ir}}var Yi=new Map;function Jo(s){var t=s.getAttribute("is")||s.nodeName,e=Yi.get(t);if(e)return e;Yi.set(t,e=[]);for(var n,i=s,l=Element.prototype;l!==i;){n=Cl(i);for(var c in n)n[c].set&&c!=="innerHTML"&&c!=="textContent"&&c!=="innerText"&&e.push(c);i=cr(i)}return e}function be(s,t,e=t){var n=new WeakSet;Fr(s,"input",async i=>{var l=i?s.defaultValue:s.value;if(l=$n(s)?Yn(l):l,e(l),fe!==null&&n.add(fe),await Po(),l!==(l=t())){var c=s.selectionStart,u=s.selectionEnd,d=s.value.length;if(s.value=l!=null?l:"",u!==null){var p=s.value.length;c===u&&u===d&&p>d?(s.selectionStart=p,s.selectionEnd=p):(s.selectionStart=c,s.selectionEnd=Math.min(u,p))}}}),Ns(t)==null&&s.value&&(e($n(s)?Yn(s.value):s.value),fe!==null&&n.add(fe)),Vn(()=>{var i=t();if(s===document.activeElement){var l=fe;if(n.has(l))return}$n(s)&&i===Yn(s.value)||s.type==="date"&&!i&&!s.value||i!==s.value&&(s.value=i!=null?i:"")})}function st(s,t,e=t){Fr(s,"change",n=>{var i=n?s.defaultChecked:s.checked;e(i)}),Ns(t)==null&&e(s.checked),Vn(()=>{var n=t();s.checked=!!n})}function $n(s){var t=s.type;return t==="number"||t==="range"}function Yn(s){return s===""?null:+s}function Gn(s,t){return s===t||(s==null?void 0:s[Ka])===t}function sl(s={},t,e,n){var i=ot.r,l=Ce;return la(()=>{var c,u;return Vn(()=>{c=u,u=[],Ns(()=>{Gn(e(...u),s)||(t(s,...u),c&&Gn(e(...c),s)&&t(null,...c))})}),()=>{let d=l;for(;d!==i&&d.parent!==null&&d.parent.f&Qn;)d=d.parent;const p=()=>{u&&Gn(e(...u),s)&&t(null,...u)},_=d.teardown;d.teardown=()=>{p(),_==null||_()}}}),s}function Ve(s,t,e,n){var Y,z;var i=!za||(e&ml)!==0,l=(e&wl)!==0,c=(e&xl)!==0,u=n,d=!0,p=void 0,_=()=>c&&i?(p!=null||(p=Xa(n)),a(p)):(d&&(d=!1,u=c?Ns(n):n),u);let h;if(l){var v=Ka in s||Il in s;h=(z=(Y=wa(s,t))==null?void 0:Y.set)!=null?z:v&&t in s?b=>s[t]=b:void 0}var k,y=!1;l?[k,y]=eo(()=>s[t]):k=s[t],k===void 0&&n!==void 0&&(k=_(),h&&(i&&Bl(),h(k)));var C;if(i?C=()=>{var b=s[t];return b===void 0?_():(d=!0,b)}:C=()=>{var b=s[t];return b!==void 0&&(u=void 0),b===void 0?u:b},i&&!(e&yl))return C;if(h){var x=s.$$legacy;return function(b,L){return arguments.length>0?((!i||!L||x||y)&&h(L?C():b),b):C()}}var S=!1,D=(e&bl?Xa:ki)(()=>(S=!1,C()));l&&a(D);var U=Ce;return function(b,L){if(arguments.length>0){const G=L?a(D):i&&l?Ue(b):b;return f(D,G),S=!0,u!==void 0&&(u=G),b}return Is&&S||U.f&is?D.v:a(D)}}const Xo="modulepreload",Zo=function(s){return"/"+s},Gi={},Qo=function(t,e,n){let i=Promise.resolve();if(e&&e.length>0){document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),u=(c==null?void 0:c.nonce)||(c==null?void 0:c.getAttribute("nonce"));i=Promise.allSettled(e.map(d=>{if(d=Zo(d),d in Gi)return;Gi[d]=!0;const p=d.endsWith(".css"),_=p?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${d}"]${_}`))return;const h=document.createElement("link");if(h.rel=p?"stylesheet":Xo,p||(h.as="script"),h.crossOrigin="",h.href=d,u&&h.setAttribute("nonce",u),document.head.appendChild(h),p)return new Promise((v,k)=>{h.addEventListener("load",v),h.addEventListener("error",()=>k(new Error(`Unable to preload CSS for ${d}`)))})}))}function l(c){const u=new Event("vite:preloadError",{cancelable:!0});if(u.payload=c,window.dispatchEvent(u),!u.defaultPrevented)throw c}return i.then(c=>{for(const u of c||[])u.status==="rejected"&&l(u.reason);return t().catch(l)})},ec="/assets/app_icon-CfHainhY.png";function tc(s,t,e,n){if(typeof t=="function"?s!==t||!n:!t.has(s))throw new TypeError("Cannot read private member from an object whose class did not declare it");return e==="m"?n:e==="a"?n.call(s):n?n.value:t.get(s)}function sc(s,t,e,n,i){if(typeof t=="function"?s!==t||!0:!t.has(s))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(s,e),e}var Sn;const os="__TAURI_TO_IPC_KEY__";function ac(s,t=!1){return window.__TAURI_INTERNALS__.transformCallback(s,t)}async function M(s,t={},e){return window.__TAURI_INTERNALS__.invoke(s,t,e)}class nc{get rid(){return tc(this,Sn,"f")}constructor(t){Sn.set(this,void 0),sc(this,Sn,t)}async close(){return M("plugin:resources|close",{rid:this.rid})}}Sn=new WeakMap;var jt;(function(s){s.WINDOW_RESIZED="tauri://resize",s.WINDOW_MOVED="tauri://move",s.WINDOW_CLOSE_REQUESTED="tauri://close-requested",s.WINDOW_DESTROYED="tauri://destroyed",s.WINDOW_FOCUS="tauri://focus",s.WINDOW_BLUR="tauri://blur",s.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",s.WINDOW_THEME_CHANGED="tauri://theme-changed",s.WINDOW_CREATED="tauri://window-created",s.WINDOW_SUSPENDED="tauri://suspended",s.WINDOW_RESUMED="tauri://resumed",s.WEBVIEW_CREATED="tauri://webview-created",s.DRAG_ENTER="tauri://drag-enter",s.DRAG_OVER="tauri://drag-over",s.DRAG_DROP="tauri://drag-drop",s.DRAG_LEAVE="tauri://drag-leave"})(jt||(jt={}));async function al(s,t){window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener(s,t),await M("plugin:event|unlisten",{event:s,eventId:t})}async function yt(s,t,e){var n;const i=typeof(e==null?void 0:e.target)=="string"?{kind:"AnyLabel",label:e.target}:(n=e==null?void 0:e.target)!==null&&n!==void 0?n:{kind:"Any"};return M("plugin:event|listen",{event:s,target:i,handler:ac(t)}).then(l=>async()=>al(s,l))}async function ic(s,t,e){return yt(s,n=>{al(s,n.id),t(n)},e)}async function rc(s,t){await M("plugin:event|emit",{event:s,payload:t})}async function lc(s,t,e){await M("plugin:event|emit_to",{target:typeof s=="string"?{kind:"AnyLabel",label:s}:s,event:t,payload:e})}const oc={engine:{backend:"auto",inference_mode:"Balanced",whisper_cpp:{model_dir:"",model_size:"tiny",device:"auto",threads:0},moonshine:{model_size:"base",language:"en"}},audio:{vad_threshold:.5,min_silence_duration_ms:500,input_device_index:null,evdev_device:null,noise_suppression:!1,gain:1,dynamic_stream:!0},ui:{show_overlay:!0,overlay_style:"mono_bars",overlay_position:"center",overlay_monitor:"primary",auto_show_settings:!0,show_notification:!1,history_enabled:!1},features:{remove_fillers:!0,custom_vocabulary:[],spoken_punctuation:!0,auto_format_lists:!0,quiet_mode:!1,snippets:{}},openai:{enabled:!1,model:"llama3.2:1b",mode:"clean",custom_prompt:null,system_prompt:"Fix grammar and punctuation only. Return only the corrected text, no commentary.",user_prompt:"{text}",endpoint:"http://localhost:11434",api_key:null,timeout_secs:8},tts:{enabled:!1,engine:"espeak",voice:"en-us-lessac-medium",voice_dir:"",stop_key:["KEY_ESCAPE"],response_overlay:!0,speed:1,gpu:!1,pocket_tts:{voice:"alba",prewarm:!1,hf_token:null,voice_dir:""}},mcp:{server_enabled:!1,record_timeout:15,visual_feedback:!0},atspi:{injection:!0,context_prompt:!0,auto_code_mode:!0}},Yt=on(oc),Es=on(!1),fi=on(!1);let Qa=!1,Jn=null;async function cc(){try{const s=await M("get_config");Yt.set(s),Es.set(!1),fi.set(!0),setTimeout(()=>{Qa=!0},0)}catch(s){console.error("loadConfig:",s),fi.set(!0),setTimeout(()=>{Qa=!0},0)}}async function nl(s){await M("save_config",{newConfig:s}),Es.set(!1)}Yt.subscribe(s=>{Qa&&(Jn&&clearTimeout(Jn),Jn=setTimeout(async()=>{try{await nl(s),console.log("Config auto-saved successfully!")}catch(t){console.error("Auto-saving config failed:",t)}},400))});cc();yt("config-changed",s=>{Qa=!1,Yt.set(s.payload),setTimeout(()=>{Qa=!0},0)}).catch(s=>{console.error("Failed to setup config-changed listener:",s)});const Ct=on({recording:!1,processing:!1,speaking:!1,mcp_recording:!1,audio_ready:!0,word_count:0,active_target_id:"default",active_target_label:"Focused Window"}),uc=cn(Ct,s=>s.recording),dc=cn(Ct,s=>s.speaking),vc=cn(Ct,s=>s.mcp_recording);cn(Ct,s=>s.word_count);cn(Ct,s=>{var t;return(t=s.active_target_label)!=null?t:"Focused Window"});yt("status-tick",s=>{Ct.set(s.payload)});M("get_status").then(Ct.set).catch(console.error);var pc=T('

General

History

When enabled, completed transcripts are saved to the History log. Disabled by default.

MCP Server

Socket: /tmp/voxctrl-mcp.sock (Linux) / \\\\.\\pipe\\voxctrl-mcp (Windows)

AT-SPI2 (Linux)

');function fc(s,t){Je(t,!0);let e=Ve(t,"cfg",15);function n(){Es.set(!0)}var i=pc(),l=r(o(i),2),c=r(o(l),2),u=r(o(c),2),d=r(l,2),p=r(o(d),2),_=r(o(p),2),h=r(p,2),v=r(o(h),2),k=r(h,2),y=r(o(k),2),C=r(d,2),x=r(o(C),2),S=r(o(x),2),D=r(x,2),U=r(o(D),2),Y=r(D,2),z=r(o(Y),2);H("change",u,n),st(u,()=>e().ui.history_enabled,b=>e(e().ui.history_enabled=b,!0)),H("change",_,n),st(_,()=>e().mcp.server_enabled,b=>e(e().mcp.server_enabled=b,!0)),H("change",v,n),st(v,()=>e().mcp.visual_feedback,b=>e(e().mcp.visual_feedback=b,!0)),H("change",y,n),be(y,()=>e().mcp.record_timeout,b=>e(e().mcp.record_timeout=b,!0)),H("change",S,n),st(S,()=>e().atspi.injection,b=>e(e().atspi.injection=b,!0)),H("change",U,n),st(U,()=>e().atspi.context_prompt,b=>e(e().atspi.context_prompt=b,!0)),H("change",z,n),st(z,()=>e().atspi.auto_code_mode,b=>e(e().atspi.auto_code_mode=b,!0)),g(s,i),Xe()}Vt(["change"]);var hc=T(''),_c=T('
'),gc=T('
');function wt(s,t){Je(t,!0);let e=Ve(t,"value",15),n=Ve(t,"options",19,()=>[]),i=Ve(t,"disabled",3,!1),l=W(!1),c=W(null),u=he(()=>n().map(C=>typeof C=="string"?{value:C,label:C,disabled:!1}:{value:C.value,label:C.label,disabled:!!C.disabled})),d=he(()=>{const C=a(u).find(x=>x.value===e());return C?C.label:e()!==void 0&&e()!==null?String(e()):""});ka(()=>{if(!a(l))return;const C=x=>{a(c)&&!a(c).contains(x.target)&&f(l,!1)};return document.addEventListener("click",C),()=>{document.removeEventListener("click",C)}});function p(C){e(C),f(l,!1),t.onchange&&t.onchange(C)}var _=gc(),h=o(_),v=o(h),k=r(h,2);{var y=C=>{var x=_c();bt(x,21,()=>a(u),gt,(S,D)=>{var U=hc();let Y;var z=o(U);J(()=>{Y=ye(U,1,"custom-dropdown-item svelte-1heock4",null,Y,{selected:a(D).value===e()}),U.disabled=a(D).disabled,ee(z,a(D).label)}),H("click",U,b=>{b.preventDefault(),b.stopPropagation(),p(a(D).value)}),g(S,U)}),g(C,x)};B(k,C=>{a(l)&&!i()&&C(y)})}sl(_,C=>f(c,C),()=>a(c)),J(()=>{h.disabled=i(),ee(v,a(d))}),H("click",h,()=>f(l,!a(l))),g(s,_),Xe()}Vt(["click"]);var bc=T('
'),mc=T('

Visual & Feedback

Overlay & HUD

Alerts & OS Integration

Application Window

');function yc(s,t){Je(t,!0);let e=Ve(t,"cfg",15),n=W(Ue([])),i=W(Ue([])),l=he(()=>[{value:"voice_card",label:"Voice Card"},{value:"waveform",label:"Waveform"},{value:"pulse",label:"Pulse Ring"},{value:"blue_wave",label:"Ocean Wave"},{value:"mono_bars",label:"Mono Bars"},{value:"spectrum",label:"Neon Spectrum"},{value:"terminal",label:"Retro Terminal"},{value:"vinyl",label:"Analog VU"},...a(n).map(w=>({value:w.name,label:w.name}))]);const c=[{value:"top",label:"Top of screen"},{value:"center",label:"Center of screen"},{value:"bottom",label:"Bottom of screen"}];let u=he(()=>[{value:"primary",label:"Primary Monitor"},...a(i).filter(w=>w.name).map(w=>({value:w.name,label:`${w.name} (${w.width}x${w.height})${w.is_primary?" [Primary]":""}`}))]);ut(async()=>{try{f(n,await M("get_custom_overlays"),!0)}catch(w){console.error("Failed to fetch custom overlays:",w)}try{f(i,await M("get_available_monitors"),!0)}catch(w){console.error("Failed to fetch available monitors:",w)}});function d(){Es.set(!0)}var p=mc(),_=r(o(p),2),h=r(o(_),2),v=r(o(h),2),k=r(h,2),y=r(o(k),2);wt(y,{get options(){return a(l)},onchange:d,get value(){return e().ui.overlay_style},set value(w){e(e().ui.overlay_style=w,!0)}});var C=r(k,2),x=r(o(C),2);wt(x,{get options(){return c},onchange:d,get value(){return e().ui.overlay_position},set value(w){e(e().ui.overlay_position=w,!0)}});var S=r(C,2),D=r(o(S),2);wt(D,{get options(){return a(u)},onchange:d,get value(){return e().ui.overlay_monitor},set value(w){e(e().ui.overlay_monitor=w,!0)}});var U=r(S,2);{var Y=w=>{var X=bc(),V=o(X),N=o(V);J(()=>{var F;return ee(N,`⚠️ Configured monitor "${(F=e().ui.overlay_monitor)!=null?F:""}" is disconnected. Using Primary Monitor.`)}),g(w,X)},z=he(()=>e().ui.overlay_monitor!=="primary"&&a(i).length>0&&!a(i).some(w=>w.name===e().ui.overlay_monitor));B(U,w=>{a(z)&&w(Y)})}var b=r(_,2),L=r(o(b),2),G=r(o(L),2),ae=r(b,2),oe=r(o(ae),2),de=r(o(oe),2);H("change",v,d),st(v,()=>e().ui.show_overlay,w=>e(e().ui.show_overlay=w,!0)),H("change",G,d),st(G,()=>e().ui.show_notification,w=>e(e().ui.show_notification=w,!0)),H("change",de,d),st(de,()=>e().ui.auto_show_settings,w=>e(e().ui.auto_show_settings=w,!0)),g(s,p),Xe()}Vt(["change"]);var wc=T(`
⚠️
Voice Model Not Downloaded

The configuration specifies a voice model ( ) that is not currently downloaded. Please select the model size to + use and download it below, or choose another model.

`),xc=T('⏳ Checking local model files...'),kc=T(' '),Tc=T('✔ Model downloaded and ready'),Ec=T('
❌ Model file missing
'),Sc=T('

'),Ac=T('

Whisper.cpp Settings

Model directory (leave blank for default)

Default model directory: ~/.local/share/voxctrl/models/

'),Cc=T(`
⚠️
Moonshine backend not included in this build

This build was compiled without Moonshine, so selecting it will fall + back to Whisper.cpp (using the Whisper model configured above). + Rebuild with --features moonshine to enable it.

`),Pc=T('⏳ Checking local model files...'),Mc=T(' '),Oc=T('✔ Model downloaded'),Dc=T('
Model not downloaded
'),Ic=T('
'),Lc=T('

Moonshine Settings

'),Nc=T('

Inference Engine

Backend

');function Rc(s,t){Je(t,!0);let e=Ve(t,"cfg",15);function n(){Es.set(!0)}const i=["tiny","tiny.en","base","base.en","small","small.en","medium","medium.en","large-v2","large-v3","large-v3-turbo"],l=[{value:"auto",label:"Auto-detect"},{value:"whisper-cpp",label:"Whisper.cpp"},{value:"moonshine",label:"Moonshine (CPU only)"}],c=[{value:"Balanced",label:"Balanced"},{value:"Aggressive",label:"Aggressive (shorter silence)"}];let u=he(()=>i.map(E=>({value:E,label:`${E}${a(h)[E]?" ✔":""}`}))),d=W(!1),p=he(()=>[{value:"auto",label:"Auto"},...a(d)?[{value:"cuda",label:"CUDA (NVIDIA)"}]:[],{value:"vulkan",label:"Vulkan (AMD/Intel)"},{value:"cpu",label:"CPU"}]);const _=[{value:"base",label:"Base"},{value:"tiny",label:"Tiny"}];let h=W(Ue({})),v=W(!1),k=W(!1),y=W(null),C=W(!0),x=W(Ue({})),S=W(!1),D=W(!1);async function U(){f(S,!0);const E={};for(const q of _)try{E[q.value]=await M("check_moonshine_downloaded",{modelSize:q.value})}catch(Z){console.error("Failed to check Moonshine download status for "+q.value,Z),E[q.value]=!1}f(x,E,!0),f(S,!1)}async function Y(E){if(!a(D)){f(D,!0);try{await M("download_moonshine_model",{modelSize:E}),a(x)[E]=!0}catch(q){alert(`Failed to download Moonshine model: ${q}`)}finally{f(D,!1)}}}async function z(){n();const E=e().engine.moonshine.model_size;a(C)&&!a(x)[E]&&await Y(E)}async function b(){f(v,!0);const E={};for(const q of i)try{E[q]=await M("check_model_downloaded",{modelSize:q,modelDir:e().engine.whisper_cpp.model_dir})}catch(Z){console.error("Failed to check download status for model "+q,Z),E[q]=!1}f(h,E,!0),f(v,!1)}async function L(E){if(!a(k)){f(k,!0);try{await M("download_model",{modelSize:E,modelDir:e().engine.whisper_cpp.model_dir}),a(h)[E]=!0}catch(q){alert(`Failed to download model: ${q}`)}finally{f(k,!1)}}}async function G(){n();const E=e().engine.whisper_cpp.model_size;a(h)[E]||await L(E)}async function ae(){const E=e().engine.whisper_cpp.model_dir;if(!E){f(y,null);return}const q=await M("check_directory_exists",{path:E});f(y,q?null:"This folder does not exist. Please create it first or leave blank for the default location.",!0),a(y)||await b()}function oe(){n()}function de(E){E.key==="Enter"&&E.currentTarget.blur()}ut(async()=>{b();try{f(C,await M("moonshine_available"),!0)}catch(E){console.error("Failed to query Moonshine availability",E)}U(),f(d,await M("cuda_enabled"),!0),!a(d)&&e().engine.whisper_cpp.device==="cuda"&&(e(e().engine.whisper_cpp.device="auto",!0),n())});var w=Nc(),X=r(o(w),2);{var V=E=>{var q=wc(),Z=r(o(q),2),ue=r(o(Z),2),ie=r(o(ue)),ne=o(ie);J(()=>ee(ne,e().engine.whisper_cpp.model_size)),g(E,q)};B(X,E=>{e().engine.backend!=="moonshine"&&!a(v)&&!a(h)[e().engine.whisper_cpp.model_size]&&E(V)})}var N=r(X,2),F=r(o(N),2),se=r(o(F),2);wt(se,{get options(){return l},onchange:n,get value(){return e().engine.backend},set value(E){e(e().engine.backend=E,!0)}});var j=r(F,2),I=r(o(j),2);wt(I,{get options(){return c},onchange:n,get value(){return e().engine.inference_mode},set value(E){e(e().engine.inference_mode=E,!0)}});var re=r(N,2);{var ve=E=>{var q=Ac(),Z=r(o(q),2),ue=r(o(Z),2);wt(ue,{get options(){return a(u)},onchange:G,get value(){return e().engine.whisper_cpp.model_size},set value(Ae){e(e().engine.whisper_cpp.model_size=Ae,!0)}});var ie=r(Z,2),ne=o(ie);{var _e=Ae=>{var Q=xc();g(Ae,Q)},Ie=Ae=>{var Q=kc(),pe=o(Q);J(()=>{var Pe;return ee(pe,`⏳ Downloading ${(Pe=e().engine.whisper_cpp.model_size)!=null?Pe:""} (GGUF format)...`)}),g(Ae,Q)},P=Ae=>{var Q=Tc();g(Ae,Q)},K=Ae=>{var Q=Ec(),pe=r(o(Q),2);H("click",pe,()=>L(e().engine.whisper_cpp.model_size)),g(Ae,Q)};B(ne,Ae=>{a(v)?Ae(_e):a(k)?Ae(Ie,1):a(h)[e().engine.whisper_cpp.model_size]?Ae(P,2):Ae(K,-1)})}var $=r(ie,2),ce=r(o($),2);wt(ce,{get options(){return a(p)},onchange:n,get value(){return e().engine.whisper_cpp.device},set value(Ae){e(e().engine.whisper_cpp.device=Ae,!0)}});var O=r($,2),A=r(o(O),2);let te;var Se=r(A,2);{var et=Ae=>{var Q=Sc(),pe=o(Q);J(()=>ee(pe,a(y))),g(Ae,Q)};B(Se,Ae=>{a(y)&&Ae(et)})}var je=r(O,2),He=r(o(je),2);J(()=>te=ye(A,1,"svelte-nfi4ak",null,te,{"field-input-error":!!a(y)})),H("change",A,oe),Ms("blur",A,ae),H("keydown",A,de),be(A,()=>e().engine.whisper_cpp.model_dir,Ae=>e(e().engine.whisper_cpp.model_dir=Ae,!0)),H("change",He,n),be(He,()=>e().engine.whisper_cpp.threads,Ae=>e(e().engine.whisper_cpp.threads=Ae,!0)),g(E,q)},le=E=>{var q=Lc(),Z=r(o(q),2);{var ue=$=>{var ce=Cc();g($,ce)};B(Z,$=>{a(C)||$(ue)})}var ie=r(Z,2),ne=r(o(ie),2);wt(ne,{get options(){return _},onchange:z,get value(){return e().engine.moonshine.model_size},set value($){e(e().engine.moonshine.model_size=$,!0)}});var _e=r(ie,2);{var Ie=$=>{var ce=Ic(),O=o(ce);{var A=je=>{var He=Pc();g(je,He)},te=je=>{var He=Mc(),Ae=o(He);J(()=>{var Q;return ee(Ae,`⏳ Downloading Moonshine ${(Q=e().engine.moonshine.model_size)!=null?Q:""} (ONNX)...`)}),g(je,He)},Se=je=>{var He=Oc();g(je,He)},et=je=>{var He=Dc(),Ae=r(o(He),2),Q=o(Ae);J(()=>{var pe;return ee(Q,`Download ${(pe=e().engine.moonshine.model_size)!=null?pe:""}`)}),H("click",Ae,()=>Y(e().engine.moonshine.model_size)),g(je,He)};B(O,je=>{a(S)?je(A):a(D)?je(te,1):a(x)[e().engine.moonshine.model_size]?je(Se,2):je(et,-1)})}g($,ce)};B(_e,$=>{a(C)&&$(Ie)})}var P=r(_e,2),K=r(o(P),2);H("change",K,n),be(K,()=>e().engine.moonshine.language,$=>e(e().engine.moonshine.language=$,!0)),g(E,q)};B(re,E=>{e().engine.backend!=="moonshine"?E(ve):E(le,-1)})}g(s,w),Xe()}Vt(["click","change","keydown"]);var Fc=T("
"),zc=T('
'),Wc=T('

Audio

Input Device

Microphone Monitor

Only opens the microphone stream when recording is triggered. If your first words are being clipped due to hardware delay, disable this feature to keep the stream always open.

Voice Activity Detection

Processing

');function qc(s,t){Je(t,!0);let e=Ve(t,"cfg",15);function n(){Es.set(!0)}let i=W(Ue([])),l=he(()=>[{value:-1,label:"Default system device"},...a(i).map(ne=>({value:ne.index,label:ne.name}))]),c=W(0),u=W(0),d=W(0),p=0,_=W(null),h;function v(){const ne=a(c);ne>a(u)?f(u,a(u)+(ne-a(u))*.45):f(u,a(u)+(ne-a(u))*.12),a(u)>a(d)?(f(d,a(u),!0),p=25):p>0?p--:f(d,Math.max(0,a(d)-.012),!0),h=requestAnimationFrame(v)}ut(async()=>{f(i,await M("list_audio_devices"),!0);try{await M("start_monitoring_audio"),f(_,await yt("audio-level",ne=>{f(c,ne.payload,!0)}),!0)}catch(ne){console.error("Failed to start audio monitoring:",ne)}h=requestAnimationFrame(v)}),Qr(async()=>{h&&cancelAnimationFrame(h),a(_)&&a(_)();try{await M("stop_monitoring_audio")}catch(ne){console.error("Failed to stop audio monitoring:",ne)}});var k=Wc(),y=r(o(k),2),C=r(o(y),2),x=r(o(C),2);{let ne=he(()=>{var _e;return(_e=e().audio.input_device_index)!=null?_e:-1});wt(x,{get value(){return a(ne)},get options(){return a(l)},onchange:_e=>{e(e().audio.input_device_index=_e<0?null:_e,!0),n()}})}var S=r(C,2),D=o(S),U=r(o(D),2);let Y;var z=r(U,2),b=o(z),L=r(D,2),G=o(L),ae=o(G);bt(ae,16,()=>Array(24),gt,(ne,_e,Ie)=>{const P=he(()=>Ie/24),K=he(()=>a(u)>=a(P)),$=he(()=>Ie>=17);var ce=Fc();let O;J(()=>O=ye(ce,1,"vu-segment svelte-1msnq7i",null,O,{active:a(K),orange:a($)})),g(ne,ce)});var oe=r(ae,2);{var de=ne=>{var _e=zc();J(Ie=>$s(_e,`left: ${Ie!=null?Ie:""}%;`),[()=>Math.min(.99,a(d))*100]),g(ne,_e)};B(oe,ne=>{a(d)>.01&&ne(de)})}var w=r(S,2),X=r(o(w),2),V=r(y,2),N=r(o(V),2),F=r(o(N),2),se=r(F,2),j=o(se),I=r(N,2),re=r(o(I),2),ve=r(V,2),le=r(o(ve),2),E=r(o(le),2),q=r(le,2),Z=r(o(q),2),ue=r(Z,2),ie=o(ue);J((ne,_e)=>{Y=ye(U,1,"vu-status-dot svelte-1msnq7i",null,Y,{active:a(c)>.005}),ee(b,a(c)>.005?"Signal Detected":"Listening..."),ee(j,ne),ee(ie,`${_e!=null?_e:""}×`)},[()=>e().audio.vad_threshold.toFixed(2),()=>e().audio.gain.toFixed(1)]),H("change",X,n),st(X,()=>e().audio.dynamic_stream,ne=>e(e().audio.dynamic_stream=ne,!0)),H("change",F,n),be(F,()=>e().audio.vad_threshold,ne=>e(e().audio.vad_threshold=ne,!0)),H("change",re,n),be(re,()=>e().audio.min_silence_duration_ms,ne=>e(e().audio.min_silence_duration_ms=ne,!0)),H("change",E,n),st(E,()=>e().audio.noise_suppression,ne=>e(e().audio.noise_suppression=ne,!0)),H("change",Z,n),be(Z,()=>e().audio.gain,ne=>e(e().audio.gain=ne,!0)),g(s,k),Xe()}Vt(["change"]);var Vc=T(''),Bc=T(' '),Uc=T('
Shell Executor Settings
Terminal Command Shell command

Use inside the command string as a placeholder to substitute transcribed speech.

'),jc=T('
Local File Writer Settings
'),Hc=T('
Network Socket settings
'),Kc=T('
FIFO Named Pipe settings
'),$c=T('
Linux DBus emitter settings
'),Yc=T(''),Gc=T(''),Jc=T(' '),Xc=T('
Method
Custom Post Body JSON Template

Must be valid JSON. Use to substitute transcribed speech.

',1),Zc=T(' '),Qc=T('
Webhook Secret Token (HMAC)
Custom Webhook Body JSON Template

Must be valid JSON. Use to substitute transcribed speech.

',1),eu=T('
API Endpoint Client settings
REST endpoint URL
'),tu=T(' '),su=T('
MCP Server Client settings
Custom Socket/Pipe Path Optional override

Leave empty to use defaults (/tmp/voxctrl-mcp.sock on Linux, \\\\.\\pipe\\voxctrl-mcp on Windows).

MCP Tool Name
Custom Tool Arguments JSON Template

Must be valid JSON. Use to substitute transcribed speech.

'),au=T(''),nu=T(''),iu=T('
');function il(s,t){Je(t,!0);let e=Ve(t,"editingTarget",15),n=Ve(t,"isNested",3,!1),i=W(!0),l=W(""),c=W(""),u=W(""),d=he(()=>!e()||e().delivery!=="exec"||(e().command||"").includes("{text}")?null:"Command must contain '{text}' placeholder."),p=he(()=>{if(!a(l).trim())return null;try{JSON.parse(a(l))}catch(S){return"Invalid JSON format: "+S.message}return a(l).includes("{text}")?null:"Arguments must contain '{text}' placeholder."}),_=he(()=>{if(!a(c).trim())return null;try{JSON.parse(a(c))}catch(S){return"Invalid JSON format: "+S.message}return a(c).includes("{text}")?null:"JSON template must contain '{text}' placeholder."}),h=he(()=>{if(!a(u).trim())return null;try{JSON.parse(a(u))}catch(S){return"Invalid JSON format: "+S.message}return a(u).includes("{text}")?null:"JSON template must contain '{text}' placeholder."});function v(S){function D(){S.style.height="auto",S.style.height=`${S.scrollHeight}px`}S.addEventListener("input",D);const U=setTimeout(D,0);return{update(){D()},destroy(){clearTimeout(U),S.removeEventListener("input",D)}}}ut(()=>{e()&&(e().processing||e(e().processing={},!0),e().file_mode||e(e().file_mode="append",!0),f(i,e().processing.apply_snippets!==!1),f(l,e().mcp_args?JSON.stringify(e().mcp_args,null,2):`{ + "text": "{text}" +}`,!0),f(c,e().http_json_template?JSON.stringify(e().http_json_template,null,2):`{ + "text": "{text}" +}`,!0),f(u,e().webhook_json_template?JSON.stringify(e().webhook_json_template,null,2):`{ + "text": "{text}" +}`,!0))});function k(){if(e()){if(e().id.trim()===""){alert("Target ID cannot be empty.");return}if(e().delivery==="exec"&&a(d)){alert("Validation Error: "+a(d));return}if(e().delivery==="mcp"){if(a(p)){alert("Validation Error: "+a(p));return}try{e(e().mcp_args=JSON.parse(a(l)),!0)}catch{alert("Invalid JSON format in MCP Custom Tool Arguments.");return}}if(e().delivery==="http"){if(a(_)){alert("Validation Error: "+a(_));return}try{e(e().http_json_template=JSON.parse(a(c)),!0)}catch{alert("Invalid JSON format in HTTP Custom Post Body.");return}}if(e().delivery==="webhook"){if(a(h)){alert("Validation Error: "+a(h));return}try{e(e().webhook_json_template=JSON.parse(a(u)),!0)}catch{alert("Invalid JSON format in Webhook Custom Post Body.");return}}e(e().processing={apply_snippets:a(i)},!0),t.onSave()}}var y=Zr(),C=Ot(y);{var x=S=>{var D=iu(),U=o(D),Y=o(U),z=o(Y),b=o(z),L=r(z,2),G=r(Y,2),ae=o(G);{var oe=Q=>{var pe=Vc(),Pe=r(o(pe),2);J(()=>Pe.disabled=!t.isNew),be(Pe,()=>e().id,Be=>e(e().id=Be,!0)),g(Q,pe)};B(ae,Q=>{n()||Q(oe)})}var de=r(ae,2),w=r(o(de),2),X=r(de,2),V=r(o(X),2);wt(V,{options:[{value:"inject",label:"Inject Text Directly (Simulate keyboard)"},{value:"clipboard",label:"Save to Clipboard"},{value:"exec",label:"Execute Command"},{value:"file",label:"Write to File"},{value:"pipe",label:"FIFO Named Pipe"},{value:"socket",label:"TCP / Unix Socket"},{value:"dbus",label:"DBus Signal"},{value:"http",label:"HTTP Custom Client"},{value:"webhook",label:"Send Webhook Event"},{value:"mcp",label:"Call MCP Server Tool"},{value:"speak",label:"Speak Text Aloud (TTS)"}],get value(){return e().delivery},set value(Q){e(e().delivery=Q,!0)}});var N=r(X,2);{var F=Q=>{var pe=Uc(),Pe=r(o(pe),2),Be=r(o(Pe),2);mt(Be,"placeholder","e.g. xdg-open {text}");var Ze=r(Be,2),ft=r(o(Ze));ft.textContent="{text}";var at=r(Ze,2);{var tt=Ke=>{var $e=Bc(),We=o($e);J(()=>{var dt;return ee(We,`⚠️ ${(dt=a(d))!=null?dt:""}`)}),g(Ke,$e)};B(at,Ke=>{a(d)&&Ke(tt)})}J(()=>ye(Be,1,`full-width-input ${a(d)?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":""}`,"svelte-oc07pw")),be(Be,()=>e().command,Ke=>e(e().command=Ke,!0)),g(Q,pe)};B(N,Q=>{e().delivery==="exec"&&Q(F)})}var se=r(N,2);{var j=Q=>{var pe=jc(),Pe=r(o(pe),2),Be=r(o(Pe),2),Ze=r(Pe,2),ft=r(o(Ze),2);wt(ft,{options:[{value:"append",label:"Append (Add to end of file)"},{value:"prepend",label:"Prepend (Add to beginning of file)"}],get value(){return e().file_mode},set value(We){e(e().file_mode=We,!0)}});var at=r(Ze,2),tt=r(o(at),2),Ke=r(at,2),$e=o(Ke);be(Be,()=>e().file_path,We=>e(e().file_path=We,!0)),be(tt,()=>e().file_prefix,We=>e(e().file_prefix=We,!0)),st($e,()=>e().file_timestamp,We=>e(e().file_timestamp=We,!0)),g(Q,pe)};B(se,Q=>{e().delivery==="file"&&Q(j)})}var I=r(se,2);{var re=Q=>{var pe=Hc(),Pe=r(o(pe),2),Be=r(o(Pe),2),Ze=r(Pe,2),ft=r(o(Ze),2),at=r(Ze,2),tt=r(o(at),2);be(Be,()=>e().socket_host,Ke=>e(e().socket_host=Ke,!0)),be(ft,()=>e().socket_port,Ke=>e(e().socket_port=Ke,!0)),be(tt,()=>e().socket_unix,Ke=>e(e().socket_unix=Ke,!0)),g(Q,pe)};B(I,Q=>{e().delivery==="socket"&&Q(re)})}var ve=r(I,2);{var le=Q=>{var pe=Kc(),Pe=r(o(pe),2),Be=r(o(Pe),2),Ze=r(Pe,2),ft=r(o(Ze),2);be(Be,()=>e().pipe_path,at=>e(e().pipe_path=at,!0)),be(ft,()=>e().response_pipe,at=>e(e().response_pipe=at,!0)),g(Q,pe)};B(ve,Q=>{e().delivery==="pipe"&&Q(le)})}var E=r(ve,2);{var q=Q=>{var pe=$c(),Pe=r(o(pe),2),Be=r(o(Pe),2);be(Be,()=>e().dbus_signal,Ze=>e(e().dbus_signal=Ze,!0)),g(Q,pe)};B(E,Q=>{e().delivery==="dbus"&&Q(q)})}var Z=r(E,2);{var ue=Q=>{var pe=eu(),Pe=r(o(pe),2),Be=r(o(Pe),2);{var Ze=$e=>{var We=Yc();be(We,()=>e().http_url,dt=>e(e().http_url=dt,!0)),g($e,We)},ft=$e=>{var We=Gc();be(We,()=>e().webhook_url,dt=>e(e().webhook_url=dt,!0)),g($e,We)};B(Be,$e=>{e().delivery==="http"?$e(Ze):$e(ft,-1)})}var at=r(Pe,2);{var tt=$e=>{var We=Xc(),dt=Ot(We),nt=r(o(dt),2);wt(nt,{options:[{value:"POST",label:"POST"},{value:"GET",label:"GET"},{value:"PUT",label:"PUT"}],get value(){return e().http_method},set value(Ye){e(e().http_method=Ye,!0)}});var Rt=r(dt,2),vt=r(o(Rt),2);mt(vt,"placeholder",'{"text": "{text}"}'),la(()=>be(vt,()=>a(c),Ye=>f(c,Ye))),ua(vt,Ye=>v==null?void 0:v(Ye));var Pt=r(vt,2),Gt=r(o(Pt));Gt.textContent="{text}";var Ss=r(Pt,2);{var kt=Ye=>{var cs=Jc(),Dt=o(cs);J(()=>{var Le;return ee(Dt,`⚠️ ${(Le=a(_))!=null?Le:""}`)}),g(Ye,cs)};B(Ss,Ye=>{a(_)&&Ye(kt)})}J(()=>ye(vt,1,fs(a(_)?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":""),"svelte-oc07pw")),g($e,We)},Ke=$e=>{var We=Qc(),dt=Ot(We),nt=r(o(dt),2),Rt=r(dt,2),vt=r(o(Rt),2);mt(vt,"placeholder",'{"text": "{text}"}'),la(()=>be(vt,()=>a(u),Ye=>f(u,Ye))),ua(vt,Ye=>v==null?void 0:v(Ye));var Pt=r(vt,2),Gt=r(o(Pt));Gt.textContent="{text}";var Ss=r(Pt,2);{var kt=Ye=>{var cs=Zc(),Dt=o(cs);J(()=>{var Le;return ee(Dt,`⚠️ ${(Le=a(h))!=null?Le:""}`)}),g(Ye,cs)};B(Ss,Ye=>{a(h)&&Ye(kt)})}J(()=>ye(vt,1,fs(a(h)?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":""),"svelte-oc07pw")),be(nt,()=>e().webhook_secret,Ye=>e(e().webhook_secret=Ye,!0)),g($e,We)};B(at,$e=>{e().delivery==="http"?$e(tt):$e(Ke,-1)})}g(Q,pe)};B(Z,Q=>{(e().delivery==="http"||e().delivery==="webhook")&&Q(ue)})}var ie=r(Z,2);{var ne=Q=>{var pe=su(),Pe=r(o(pe),2),Be=r(o(Pe),2),Ze=r(Pe,2),ft=r(o(Ze),2),at=r(Ze,2),tt=r(o(at),2);mt(tt,"placeholder",'{"text": "{text}"}'),la(()=>be(tt,()=>a(l),nt=>f(l,nt))),ua(tt,nt=>v==null?void 0:v(nt));var Ke=r(tt,2),$e=r(o(Ke));$e.textContent="{text}";var We=r(Ke,2);{var dt=nt=>{var Rt=tu(),vt=o(Rt);J(()=>{var Pt;return ee(vt,`⚠️ ${(Pt=a(p))!=null?Pt:""}`)}),g(nt,Rt)};B(We,nt=>{a(p)&&nt(dt)})}J(()=>ye(tt,1,fs(a(p)?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":""),"svelte-oc07pw")),be(Be,()=>e().mcp_path,nt=>e(e().mcp_path=nt,!0)),be(ft,()=>e().mcp_tool,nt=>e(e().mcp_tool=nt,!0)),g(Q,pe)};B(ie,Q=>{e().delivery==="mcp"&&Q(ne)})}var _e=r(ie,2),Ie=r(o(_e),2),P=o(Ie),K=r(Ie,2),$=o(K),ce=r(K,2);{var O=Q=>{var pe=au(),Pe=o(pe);st(Pe,()=>e().strip_newlines,Be=>e(e().strip_newlines=Be,!0)),g(Q,pe)};B(ce,Q=>{e().delivery==="inject"&&Q(O)})}var A=r(ce,2);{var te=Q=>{var pe=nu(),Pe=o(pe);st(Pe,()=>a(i),Be=>f(i,Be)),g(Q,pe)};B(A,Q=>{e().processing&&Q(te)})}var Se=r(A,2),et=r(o(Se),2),je=r(G,2),He=o(je),Ae=r(He,2);J(()=>{ye(D,1,`modal-backdrop ${n()?"target-modal-backdrop":""}`,"svelte-oc07pw"),ee(b,t.isNew?"Create Target":"Edit Target")}),H("click",L,function(...Q){var pe;(pe=t.onCancel)==null||pe.apply(this,Q)}),be(w,()=>e().label,Q=>e(e().label=Q,!0)),st(P,()=>e().append_newline,Q=>e(e().append_newline=Q,!0)),st($,()=>e().send_on_release,Q=>e(e().send_on_release=Q,!0)),be(et,()=>e().initial_prompt,Q=>e(e().initial_prompt=Q,!0)),H("click",He,function(...Q){var pe;(pe=t.onCancel)==null||pe.apply(this,Q)}),H("click",Ae,k),g(S,D)};B(C,S=>{e()&&S(x)})}g(s,y),Xe()}Vt(["click"]);var ru=T('
⚠️ Conflict detected: Some key bindings share the same key combination and gesture type. Disabling one of the conflicting binds will fix the problem.
'),lu=T('CONFLICT'),ou=T('LLM'),cu=T(' '),uu=T(' ',1),du=T('Delete? ',1),vu=T(''),pu=T('
'),fu=T('

No keyboard bindings defined. Create a binding to link a physical hotkey to a routing target!

'),hu=T(''),_u=T('
',1),gu=T(''),bu=T('
'),mu=T(``),yu=T(''),wu=T('
'),xu=T(' '),ku=T('
(Click / Tab here to record)',1),Tu=T(''),Eu=T('
Press the trigger key now...
'),Su=T(' (Click / Tab here to change trigger key)',1),Au=T(''),Cu=T('
Subkey Trigger (Pressed Key)
'),Pu=T('⚠️ Warning: This key combination and gesture type conflicts with another existing binding.'),Mu=T('⚠️ Validation Error: Prompt template MUST contain the placeholder.'),Ou=T('

Prompt template MUST contain the placeholder. Leave empty to inherit the default user prompt.

'),Du=T('
System Prompt Override LLM Prompt

Overrides the default system prompt configured in Settings → OpenAI API. Leave empty to inherit it.

User Prompt Template LLM Prompt
'),Iu=T(''),Lu=T('

Hotkey Bindings

Bind physical keyboard combinations to your output targets. Each hotkey supports customizable triggers (double-taps, holding keys, etc.)

',1);function Nu(s,t){Je(t,!0);let e=W(Ue([])),n=W(Ue([])),i=W(null),l=W(!1),c=W(null),u=W(null),d=W(null),p=W(!1),_=W(null),h=W(null),v=W(!1),k=W(""),y=W("custom"),C=W(""),x=W("");function S(O,A,te){const Se=[...O].sort().join(","),et=A==="chord"&&te?`+${te}`:"";return`${A}:${Se}${et}`}let D=he(()=>{const O=new Map;for(const te of a(n))if(te.keys&&te.keys.length>0){const Se=S(te.keys,te.gesture,te.subkey);O.set(Se,(O.get(Se)||0)+1)}const A=new Set;for(const[te,Se]of O.entries())Se>1&&A.add(te);return A}),U=he(()=>{const O=new Map;for(const te of a(n))if(!te.disabled&&te.keys&&te.keys.length>0){const Se=S(te.keys,te.gesture,te.subkey);O.set(Se,(O.get(Se)||0)+1)}const A=new Set;for(const[te,Se]of O.entries())Se>1&&A.add(te);return A}),Y=he(()=>{if(!a(i)||!a(i).keys||a(i).keys.length===0)return!1;const O=S(a(i).keys,a(i).gesture,a(i).subkey);return a(n).some(A=>A.id!==a(i).id&&S(A.keys,A.gesture,A.subkey)===O)});function z(O){function A(){O.style.height="auto",O.style.height=`${O.scrollHeight}px`}O.addEventListener("input",A);const te=setTimeout(A,0);return{update(){A()},destroy(){clearTimeout(te),O.removeEventListener("input",A)}}}ut(async()=>{f(e,await M("get_targets"),!0),f(n,await M("get_bindings"),!0)});async function b(){try{await M("save_targets",{targets:a(e)}),console.log("Targets auto-saved successfully!")}catch(O){console.error("Failed to save targets:",O)}}async function L(){try{await M("save_bindings",{bindings:a(n)}),console.log("Bindings auto-saved successfully!")}catch(O){console.error("Failed to save bindings:",O)}}function G(O){return(O.target_ids&&O.target_ids.length>0?O.target_ids:[O.target_id]).map(te=>{const Se=a(e).find(et=>et.id===te);return Se?Se.label:te==="default"?"Focused Window":te}).join(", ")}function ae(O){const A=a(e).find(te=>te.id===O);return A?`${A.label} (${A.delivery})`:O==="default"?"Focused Window":O}function oe(){if(a(e).length===0){alert("Please create at least one Output Target before making a hotkey binding.");return}f(l,!0),f(v,!1),f(k,""),f(y,"custom"),f(C,""),f(x,""),f(i,{id:"binding_"+Math.random().toString(36).substring(2,6),label:"New Binding",keys:["KEY_LEFTMETA","KEY_SPACE"],gesture:"hold",target_id:a(e)[0].id,target_ids:[a(e)[0].id],tap_ms:300,hold_threshold_ms:1e3,subkey:"",disabled:!1,openai_enabled:!1,openai_model:"",openai_mode:"custom",openai_prompt:"",openai_system_prompt:""},!0)}function de(O){f(l,!1);const A=JSON.parse(JSON.stringify(O));A.target_ids||(A.target_ids=A.target_id?[A.target_id]:[]),f(v,A.openai_enabled===!0),f(k,A.openai_model||"",!0),f(y,A.openai_mode||"custom",!0),f(C,A.openai_prompt||"",!0),f(x,A.openai_system_prompt||"",!0),f(i,A,!0)}async function w(O){f(n,a(n).map(A=>A.id===O?{...A,disabled:!A.disabled}:A),!0),await L()}function X(){if(!a(i))return;a(i).target_ids||(a(i).target_ids=[a(i).target_id]);const O=a(e).find(te=>!a(i).target_ids.includes(te.id)),A=O?O.id:a(e)[0].id;a(i).target_ids=[...a(i).target_ids,A]}function V(O){!a(i)||!a(i).target_ids||(a(i).target_ids=a(i).target_ids.filter((A,te)=>te!==O))}async function N(){if(a(i)){if(a(i).id.trim()===""){alert("Binding ID cannot be empty.");return}if(a(i).keys.length===0){alert("Please capture at least one hotkey before saving.");return}if(a(i).gesture==="chord"&&(!a(i).subkey||a(i).subkey.trim()==="")){alert("Please capture a subkey trigger for the chord combo before saving.");return}if(a(v)&&a(y)==="custom"&&!a(C).includes("{text}")){alert(`LLM Configuration Error: +Your custom prompt template MUST contain the '{text}' placeholder so the model knows where to insert the transcribed text. + +Example: +write a haiku about {text}`);return}if(a(i).openai_enabled=a(v),a(i).openai_model=a(k),a(i).openai_mode=a(y),a(i).openai_prompt=a(C),a(i).openai_system_prompt=a(x),a(i).target_ids&&a(i).target_ids.length>0){if(a(i).target_ids=a(i).target_ids.filter(A=>A.trim()!==""),a(i).target_ids.length===0){alert("Please assign at least one Output Target.");return}if(new Set(a(i).target_ids).size!==a(i).target_ids.length){alert(`Duplicate targets detected. +You cannot assign the same Output Target multiple times to a single keybind.`);return}a(i).target_id=a(i).target_ids[0]}else a(i).target_id="",a(i).target_ids=[];if(a(l)){if(a(n).some(O=>O.id===a(i).id)){alert("Binding with this ID already exists.");return}f(n,[...a(n),a(i)],!0)}else f(n,a(n).map(O=>O.id===a(i).id?a(i):O),!0);f(i,null),f(c,null),await L()}}async function F(O){f(n,a(n).filter(A=>A.id!==O),!0),await L()}function se(O,A){const te=A.toUpperCase();return O==="Control"?"KEY_LEFTCTRL":O==="Alt"?"KEY_LEFTALT":O==="Shift"?"KEY_LEFTSHIFT":O==="Meta"||O==="OS"||O==="Super"?"KEY_LEFTMETA":te==="SPACE"?"KEY_SPACE":te==="ENTER"?"KEY_ENTER":te==="ESCAPE"||te==="ESC"?"KEY_ESC":te==="TAB"?"KEY_TAB":te==="BACKSPACE"?"KEY_BACKSPACE":te==="DELETE"?"KEY_DELETE":/^KEY[A-Z]$/.test(te)?`KEY_${te.slice(3)}`:te.startsWith("KEY")?te:te.startsWith("DIGIT")?`KEY_${te.replace("DIGIT","")}`:te.startsWith("ARROW")?`KEY_${te.replace("ARROW","")}`:te.startsWith("F")&&te.length>1?`KEY_${te}`:O.length===1?`KEY_${O.toUpperCase()}`:`KEY_${te}`}let j=W(Ue([]));function I(O){if(!a(c)||!a(i))return;O.preventDefault(),O.stopPropagation();const A=se(O.key,O.code);a(c)==="keys"?(a(j).includes(A)||f(j,[...a(j),A],!0),O.key==="Escape"&&(a(i).keys=[...a(j)],f(j,[],!0),f(c,null))):a(c)==="subkey"&&(a(i).subkey=A,f(c,null))}function re(O){!a(c)||!a(i)||(O.preventDefault(),O.stopPropagation(),a(c)==="keys"&&(a(j).length>0&&(a(i).keys=[...a(j)]),f(j,[],!0),f(c,null)))}function ve(){a(c)&&(a(c)==="keys"&&a(j).length>0&&a(i)&&(a(i).keys=[...a(j)],f(j,[],!0)),f(c,null))}function le(O){f(_,O,!0),f(p,!0),f(d,{id:"new_target_"+Math.random().toString(36).substring(2,6),label:"New Target",delivery:"inject",file_prefix:"- ",file_timestamp:!0,file_mode:"append",http_method:"POST",http_json_template:{text:"{text}"},webhook_json_template:{text:"{text}"},mcp_tool:"speak_text",mcp_args:{text:"{text}"},send_on_release:!1,append_newline:!0,strip_newlines:!1,processing:{apply_snippets:!0}},!0)}function E(){f(d,null),f(_,null)}async function q(){if(a(d)){if(a(e).some(O=>O.id===a(d).id)){alert("Target with this ID already exists.");return}f(e,[...a(e),a(d)],!0),a(_)!==null&&a(i)&&(a(i).target_ids||(a(i).target_ids=[]),a(i).target_ids[a(_)]=a(d).id),f(d,null),f(_,null),await b()}}var Z=Lu(),ue=Ot(Z),ie=r(o(ue),2),ne=r(ie,2);{var _e=O=>{var A=ru();g(O,A)};B(ne,O=>{a(D).size>0&&O(_e)})}var Ie=r(ne,2);bt(Ie,21,()=>a(n),gt,(O,A)=>{var te=pu();let Se;var et=o(te);{var je=Le=>{var pt=lu();g(Le,pt)},He=he(()=>!a(A).disabled&&a(A).keys&&a(A).keys.length>0&&a(U).has(S(a(A).keys,a(A).gesture,a(A).subkey)));B(et,Le=>{a(He)&&Le(je)})}var Ae=r(et,2),Q=o(Ae),pe=o(Q);let Pe;var Be=o(pe),Ze=r(pe,2);{var ft=Le=>{var pt=ou();g(Le,pt)};B(Ze,Le=>{a(A).openai_enabled&&Le(ft)})}var at=r(Q,2),tt=o(at),Ke=o(tt);bt(Ke,17,()=>a(A).keys,gt,(Le,pt)=>{var Bt=cu(),R=o(Bt);J(ge=>ee(R,ge),[()=>a(pt).replace("KEY_","")]),g(Le,Bt)});var $e=r(Ke,2);{var We=Le=>{var pt=uu(),Bt=r(Ot(pt),2),R=o(Bt);J(ge=>ee(R,ge),[()=>a(A).subkey.replace("KEY_","")]),g(Le,pt)};B($e,Le=>{a(A).gesture==="chord"&&a(A).subkey&&Le(We)})}var dt=r(tt,2),nt=o(dt),Rt=r(at,2),vt=o(Rt),Pt=r(Rt,2),Gt=o(Pt),Ss=o(Gt),kt=r(Gt,2),Ye=r(kt,2);{var cs=Le=>{var pt=du(),Bt=r(Ot(pt),2),R=r(Bt,2);H("click",Bt,()=>{F(a(A).id),f(u,null)}),H("click",R,()=>f(u,null)),g(Le,pt)},Dt=Le=>{var pt=vu();H("click",pt,()=>f(u,a(A).id,!0)),g(Le,pt)};B(Ye,Le=>{a(u)===a(A).id?Le(cs):Le(Dt,-1)})}J((Le,pt,Bt)=>{Se=ye(te,1,"binding-item glass svelte-w4d8v7",null,Se,Le),Pe=ye(pe,1,"binding-title svelte-w4d8v7",null,Pe,pt),ee(Be,a(A).label||a(A).id),ee(nt,a(A).gesture),ee(vt,Bt),ee(Ss,a(A).disabled?"Enable":"Disable")},[()=>({disabled:a(A).disabled,"has-conflict":a(A).keys&&a(A).keys.length>0&&a(D).has(S(a(A).keys,a(A).gesture,a(A).subkey)),"active-conflict":!a(A).disabled&&a(A).keys&&a(A).keys.length>0&&a(U).has(S(a(A).keys,a(A).gesture,a(A).subkey))}),()=>({"has-conflict":!a(A).disabled&&a(A).keys&&a(A).keys.length>0&&a(U).has(S(a(A).keys,a(A).gesture,a(A).subkey))}),()=>G(a(A))]),H("click",Gt,()=>w(a(A).id)),H("click",kt,()=>de(a(A))),g(O,te)},O=>{var A=fu();g(O,A)});var P=r(ue,2);{var K=O=>{var A=Iu(),te=o(A),Se=o(te),et=o(Se),je=o(et),He=r(et,2),Ae=r(Se,2),Q=o(Ae),pe=r(o(Q),2),Pe=r(Q,2),Be=r(o(Pe),2),Ze=r(Pe,2),ft=o(Ze),at=r(o(ft),2),tt=r(ft,2);bt(tt,21,()=>a(i).target_ids||[],gt,(me,Me,Ne)=>{var Ge=bu(),Mt=o(Ge),Oe=o(Mt),qe=o(Oe),ke=r(Oe,2);{var rt=Qe=>{var Re=_u(),bs=Ot(Re),Gs=r(bs,2),vn=o(Gs);bt(vn,17,()=>a(e),gt,(pn,qa)=>{var fn=hu(),ol=o(fn);J(hn=>{var Ni,Ri;fn.disabled=hn,ee(ol,`${(Ni=a(qa).label)!=null?Ni:""} (${(Ri=a(qa).delivery)!=null?Ri:""})`)},[()=>a(i).target_ids.includes(a(qa).id)&&a(qa).id!==a(Me)]),H("click",fn,hn=>{hn.preventDefault(),hn.stopPropagation(),a(i).target_ids[Ne]=a(qa).id,f(h,null)}),g(pn,fn)});var ll=r(vn,2);H("click",bs,()=>f(h,null)),H("click",ll,pn=>{pn.preventDefault(),pn.stopPropagation(),f(h,null),le(Ne)}),g(Qe,Re)};B(ke,Qe=>{a(h)===Ne&&Qe(rt)})}var Tt=r(Mt,2);{var Xt=Qe=>{var Re=gu();H("click",Re,()=>V(Ne)),g(Qe,Re)};B(Tt,Qe=>{Ne>0&&Qe(Xt)})}J(Qe=>ee(qe,Qe),[()=>ae(a(Me))]),H("click",Oe,()=>f(h,a(h)===Ne?null:Ne,!0)),g(me,Ge)});var Ke=r(Ze,2),$e=r(o(Ke),2);wt($e,{options:[{value:"hold",label:"Hold keys to dictate (Release to transcribe)"},{value:"toggle",label:"Tap once to start recording, tap again to finish"},{value:"double_tap",label:"Double-tap hotkey to trigger recording"},{value:"double_tap_hold",label:"Double-tap & hold keys to dictate (Release to transcribe)"},{value:"chord",label:"Chord combo (Held base keys + sub key)"}],get value(){return a(i).gesture},set value(me){a(i).gesture=me}});var We=r(Ke,2);{var dt=me=>{var Me=mu(),Ne=r(o(Me),2);be(Ne,()=>a(i).hold_threshold_ms,Ge=>a(i).hold_threshold_ms=Ge),g(me,Me)};B(We,me=>{(a(i).gesture==="hold"||a(i).gesture==="double_tap_hold")&&me(dt)})}var nt=r(We,2);{var Rt=me=>{var Me=yu(),Ne=r(o(Me),2);be(Ne,()=>a(i).tap_ms,Ge=>a(i).tap_ms=Ge),g(me,Me)};B(nt,me=>{(a(i).gesture==="double_tap"||a(i).gesture==="double_tap_hold")&&me(Rt)})}var vt=r(nt,2),Pt=o(vt),Gt=o(Pt),Ss=o(Gt),kt=r(Gt,2),Ye=o(kt);{var cs=me=>{var Me=wu(),Ne=r(o(Me),2),Ge=o(Ne);J(Mt=>ee(Ge,Mt),[()=>a(j).length>0?a(j).join(" + ").replace(/KEY_/g,""):"Press your physical shortcut combination now..."]),g(me,Me)},Dt=me=>{var Me=Tu(),Ne=o(Me);{var Ge=Oe=>{var qe=ku(),ke=Ot(qe);bt(ke,21,()=>a(i).keys,gt,(rt,Tt)=>{var Xt=xu(),Qe=o(Xt);J(Re=>ee(Qe,Re),[()=>a(Tt).replace("KEY_","")]),g(rt,Xt)}),g(Oe,qe)},Mt=Oe=>{var qe=Ee("⚠️ Click/Focus here to press keys!");g(Oe,qe)};B(Ne,Oe=>{a(i).keys.length>0?Oe(Ge):Oe(Mt,-1)})}g(me,Me)};B(Ye,me=>{a(c)==="keys"?me(cs):me(Dt,-1)})}var Le=r(Pt,2);{var pt=me=>{var Me=Cu(),Ne=r(o(Me),2),Ge=o(Ne);{var Mt=qe=>{var ke=Eu();g(qe,ke)},Oe=qe=>{var ke=Au(),rt=o(ke);{var Tt=Qe=>{var Re=Su(),bs=Ot(Re),Gs=o(bs);J(vn=>ee(Gs,vn),[()=>a(i).subkey.replace("KEY_","")]),g(Qe,Re)},Xt=Qe=>{var Re=Ee("⚠️ Click/Focus here to press the trigger key!");g(Qe,Re)};B(rt,Qe=>{a(i).subkey?Qe(Tt):Qe(Xt,-1)})}g(qe,ke)};B(Ge,qe=>{a(c)==="subkey"?qe(Mt):qe(Oe,-1)})}J(qe=>ye(Ne,1,qe,"svelte-w4d8v7"),[()=>fs(["border-2 rounded-desktop p-4 text-center cursor-pointer outline-none transition-all duration-200 flex flex-col items-center justify-center min-h-[70px]",a(c)==="subkey"?"border-solid border-[#f43f5e] bg-[rgba(244,63,94,0.05)] animate-border-pulse":a(Y)?"border-solid border-[#fbbf24] bg-[rgba(251,191,36,0.05)] hover:border-[#fbbf24]/80":"border-dashed border-white/5 bg-black/25 hover:border-accent-blue hover:bg-black/35 focus:border-accent-blue focus:bg-black/35"].join(" "))]),H("click",Ne,()=>f(c,"subkey")),Ms("focus",Ne,()=>f(c,"subkey")),Ms("blur",Ne,()=>ve()),H("keydown",Ne,I),H("keyup",Ne,re),g(me,Me)};B(Le,me=>{a(i).gesture==="chord"&&me(pt)})}var Bt=r(Le,2);{var R=me=>{var Me=Pu();g(me,Me)};B(Bt,me=>{a(Y)&&me(R)})}var ge=r(vt,2),we=r(o(ge),2),it=o(we),It=r(we,2);{var Jt=me=>{var Me=Du(),Ne=o(Me),Ge=r(o(Ne),2),Mt=r(Ne,2),Oe=r(o(Mt),2);la(()=>be(Oe,()=>a(x),Re=>f(x,Re))),ua(Oe,Re=>z==null?void 0:z(Re));var qe=r(Mt,2),ke=r(o(qe),2);mt(ke,"placeholder","e.g. write a haiku about {text}"),la(()=>be(ke,()=>a(C),Re=>f(C,Re))),ua(ke,Re=>z==null?void 0:z(Re));var rt=r(ke,2);{var Tt=Re=>{var bs=Mu(),Gs=r(o(bs));Gs.textContent="{text}",g(Re,bs)},Xt=he(()=>a(C)&&!a(C).includes("{text}")),Qe=Re=>{var bs=Ou(),Gs=r(o(bs));Gs.textContent="{text}",g(Re,bs)};B(rt,Re=>{a(Xt)?Re(Tt):Re(Qe,-1)})}J(Re=>ye(ke,1,Re,"svelte-w4d8v7"),[()=>fs(a(C)&&!a(C).includes("{text}")?"border-red-500! ring-2! ring-red-500/20! focus:border-red-500! focus:ring-red-500/20!":"")]),be(Ge,()=>a(k),Re=>f(k,Re)),g(me,Me)};B(It,me=>{a(v)&&me(Jt)})}var gs=r(Ae,2),Rs=o(gs),Ys=r(Rs,2);J(me=>{ee(je,a(l)?"Create Hotkey Binding":"Edit Hotkey Binding"),pe.disabled=!a(l),ee(Ss,a(i).gesture==="chord"?"Base Combo (Held Keys)":"Hotkey Keybind Selection"),ye(kt,1,me,"svelte-w4d8v7")},[()=>fs(["border-2 rounded-desktop p-4 text-center cursor-pointer outline-none transition-all duration-200 flex flex-col items-center justify-center min-h-[70px]",a(c)==="keys"?"border-solid border-[#f43f5e] bg-[rgba(244,63,94,0.05)] animate-border-pulse":a(Y)?"border-solid border-[#fbbf24] bg-[rgba(251,191,36,0.05)] hover:border-[#fbbf24]/80":"border-dashed border-white/5 bg-black/25 hover:border-accent-blue hover:bg-black/35 focus:border-accent-blue focus:bg-black/35"].join(" "))]),H("click",He,()=>{f(i,null),f(c,null)}),be(pe,()=>a(i).id,me=>a(i).id=me),be(Be,()=>a(i).label,me=>a(i).label=me),H("click",at,X),H("click",kt,()=>f(c,"keys")),Ms("focus",kt,()=>f(c,"keys")),Ms("blur",kt,()=>ve()),H("keydown",kt,I),H("keyup",kt,re),st(it,()=>a(v),me=>f(v,me)),H("click",Rs,()=>{f(i,null),f(c,null)}),H("click",Ys,N),g(O,A)};B(P,O=>{a(i)&&O(K)})}var $=r(P,2);{var ce=O=>{il(O,{isNew:!0,get existingTargets(){return a(e)},isNested:!0,onSave:q,onCancel:E,get editingTarget(){return a(d)},set editingTarget(A){f(d,A,!0)}})};B($,O=>{a(d)&&O(ce)})}H("click",ie,oe),g(s,Z),Xe()}Vt(["click","keydown","keyup"]);var Ru=T('
'),Fu=T('
'),zu=T('
'),Wu=T('
'),qu=T('
'),Vu=T('
'),Bu=T('
Speech: Plays transcribed text via TTS
'),Uu=T('Delete? ',1),ju=T(''),Hu=T('
'),Ku=T('
🎯

No output targets defined. Create one to route your transcription output!

'),$u=T('

Output Targets

Define routing destinations where transcribed text is typed, copied, piped, or sent over network sockets.

',1);function Yu(s,t){Je(t,!0);let e=W(Ue([])),n=W(Ue([])),i=W(null),l=W(!1),c=W(null),u=W(null);ut(async()=>{f(e,await M("get_targets"),!0),f(n,await M("get_bindings"),!0)});async function d(){try{await M("save_targets",{targets:a(e)}),console.log("Targets auto-saved successfully!")}catch(z){console.error("Failed to save targets:",z)}}async function p(){try{await M("save_bindings",{bindings:a(n)}),console.log("Bindings auto-saved successfully!")}catch(z){console.error("Failed to save bindings:",z)}}function _(){f(l,!0),f(i,{id:"new_target_"+Math.random().toString(36).substring(2,6),label:"New Target",delivery:"inject",file_prefix:"- ",file_timestamp:!0,file_mode:"append",http_method:"POST",http_json_template:{text:"{text}"},webhook_json_template:{text:"{text}"},mcp_tool:"speak_text",mcp_args:{text:"{text}"},send_on_release:!1,append_newline:!0,strip_newlines:!1,processing:{apply_snippets:!0}},!0)}function h(z){f(l,!1),f(c,z.id,!0);const b=JSON.parse(JSON.stringify(z));b.processing||(b.processing={}),b.file_mode||(b.file_mode="append"),f(i,b,!0)}function v(){f(i,null),f(c,null)}async function k(){if(a(i)){if(a(l))f(e,[...a(e),a(i)],!0);else{if(a(c)&&a(c)!==a(i).id){let z=!1;f(n,a(n).map(b=>{let L=!1,G=b.target_ids?[...b.target_ids]:[b.target_id];for(let ae=0;aez.id===a(c)?a(i):z),!0)}f(i,null),f(c,null),await d()}}async function y(z){const b=a(n).filter(L=>(L.target_ids&&L.target_ids.length>0?L.target_ids:[L.target_id]).includes(z)).map(L=>L.label||L.id);if(b.length>0){alert(`Cannot delete target. It is currently being used by hotkeys: ${b.join(", ")}`);return}f(e,a(e).filter(L=>L.id!==z),!0),await d()}var C=$u(),x=Ot(C),S=r(o(x),2),D=r(S,2);bt(D,21,()=>a(e),gt,(z,b)=>{var L=Hu(),G=o(L),ae=o(G),oe=o(ae),de=o(oe),w=r(oe,2),X=o(w),V=r(ae,2);{var N=$=>{var ce=Ru(),O=o(ce);J(()=>{var A;return ee(O,`Cmd: ${(A=a(b).command)!=null?A:""}`)}),g($,ce)};B(V,$=>{a(b).delivery==="exec"&&$(N)})}var F=r(V,2);{var se=$=>{var ce=Fu(),O=o(ce);J(()=>{var A;return ee(O,`File: ${(A=a(b).file_path)!=null?A:""}`)}),g($,ce)};B(F,$=>{a(b).delivery==="file"&&$(se)})}var j=r(F,2);{var I=$=>{var ce=zu(),O=o(ce);J(()=>{var A,te;return ee(O,`Socket: ${(A=a(b).socket_host)!=null?A:""}:${(te=a(b).socket_port)!=null?te:""}`)}),g($,ce)};B(j,$=>{a(b).delivery==="socket"&&$(I)})}var re=r(j,2);{var ve=$=>{var ce=Wu(),O=o(ce),A=r(O);{var te=Se=>{var et=Ee();J(()=>{var je;return ee(et,`→ ${(je=a(b).response_pipe)!=null?je:""}`)}),g(Se,et)};B(A,Se=>{a(b).response_pipe&&Se(te)})}J(()=>{var Se;return ee(O,`Pipe: ${(Se=a(b).pipe_path)!=null?Se:""} `)}),g($,ce)};B(re,$=>{a(b).delivery==="pipe"&&$(ve)})}var le=r(re,2);{var E=$=>{var ce=qu(),O=o(ce);J(()=>{var A;return ee(O,`API: ${(A=a(b).http_url||a(b).webhook_url)!=null?A:""}`)}),g($,ce)};B(le,$=>{(a(b).delivery==="http"||a(b).delivery==="webhook")&&$(E)})}var q=r(le,2);{var Z=$=>{var ce=Vu(),O=o(ce);J(()=>{var A;return ee(O,`MCP Tool: ${(A=a(b).mcp_tool||"speak_text")!=null?A:""}`)}),g($,ce)};B(q,$=>{a(b).delivery==="mcp"&&$(Z)})}var ue=r(q,2);{var ie=$=>{var ce=Bu();g($,ce)};B(ue,$=>{a(b).delivery==="speak"&&$(ie)})}var ne=r(ue,2),_e=o(ne),Ie=r(_e,2);{var P=$=>{var ce=Uu(),O=r(Ot(ce),2),A=r(O,2);H("click",O,()=>{y(a(b).id),f(u,null)}),H("click",A,()=>f(u,null)),g($,ce)},K=$=>{var ce=ju();H("click",ce,()=>f(u,a(b).id,!0)),g($,ce)};B(Ie,$=>{a(u)===a(b).id?$(P):$(K,-1)})}J(()=>{ee(de,a(b).label),ee(X,a(b).delivery)}),H("click",_e,()=>h(a(b))),g(z,L)},z=>{var b=Ku();g(z,b)});var U=r(x,2);{var Y=z=>{il(z,{get isNew(){return a(l)},get existingTargets(){return a(e)},isNested:!1,onSave:k,onCancel:v,get editingTarget(){return a(i)},set editingTarget(b){f(i,b,!0)}})};B(U,z=>{a(i)&&z(Y)})}H("click",S,_),g(s,C),Xe()}Vt(["click"]);var Gu=T('

Use CUDA GPU acceleration (ONNX Runtime). Falls back to CPU if unavailable.

',1),Ju=T('
Run speed
'),Xu=T('

'),Zu=T('⏳ Checking local voice files...'),Qu=T(' '),ed=T('
'),td=T('

'),sd=T('

Piper Voice

Voice directory (leave blank for default)

Default voice directory: ~/.local/share/voxctrl/piper-voices/

'),ad=T('⏳ Checking local model files...'),nd=T('⏳ Downloading Pocket-TTS model & voice clip (may take a few minutes)...'),id=T('
'),rd=T('

'),ld=T(`

Pocket-TTS Voice

HuggingFace access token

Pocket-TTS model weights are hosted on a gated HuggingFace repo. Create a token at huggingface.co/settings/tokens and accept the license at huggingface.co/kyutai/pocket-tts before downloading.

Custom voice directory (leave blank for default)

Drop a .wav reference clip into this folder to add it to the voice list — + the filename (without extension) becomes the voice's id, e.g. narrator.wav adds + "Narrator (Custom)". Naming a clip after a built-in voice (e.g. alba.wav) replaces + that voice's reference clip. Default: ~/.local/share/voxctrl/pocket-tts-voices/

`),od=T('
'),cd=T(' '),ud=T('
(Click / Tab here to record a new stop key)',1),dd=T(''),vd=T('

Text to Speech

TTS Engine

Playback

Stop Key Bind

Press a key combo to immediately stop TTS playback — works even when this window is hidden.

');function pd(s,t){Je(t,!0);let e=Ve(t,"cfg",15);function n(){Es.set(!0)}let i=W(null),l=W(0),c=W(!1),u=null,d=null,p=null,_=null,h=W(!1),v=W(null),k=0;function y(){f(c,!0),f(l,0),f(i,null),k=performance.now(),u&&clearInterval(u),u=setInterval(()=>{f(l,Math.round(performance.now()-k),!0),a(l)>1e4&&(clearInterval(u),f(c,!1),f(i,null))},10)}const C=["en-us-libritts-high","en-us-amy-low","en-us-kathleen-low","en-gb-southern_english_female-low","en-us-ryan-high","en-us-ryan-medium","en-us-ryan-low","en-us-lessac-medium","en-us-lessac-low","en-us-danny-low","en-gb-alan-low"];let x=W(Ue({})),S=W(!1),D=W(!1),U=W(!1),Y=W(null);async function z(){f(S,!0);const R={};for(const ge of C)try{R[ge]=await M("check_voice_downloaded",{voiceName:ge,voiceDir:e().tts.voice_dir})}catch(we){console.error("Failed to check download status for voice "+ge,we),R[ge]=!1}f(x,R,!0),f(S,!1)}async function b(R){if(!a(D)){f(D,!0);try{await M("download_voice",{voiceName:R,voiceDir:e().tts.voice_dir}),a(x)[R]=!0}catch(ge){alert(`Failed to download voice: ${ge}`)}finally{f(D,!1)}}}async function L(){const R=e().tts.voice_dir;if(!R){f(Y,null);return}const ge=await M("check_directory_exists",{path:R});f(Y,ge?null:"This folder does not exist. Please create it first or leave blank for the default location.",!0),a(Y)||await z()}function G(){n()}function ae(R){R.key==="Enter"&&R.currentTarget.blur()}async function oe(){n()}async function de(){if(a(U))return;if(a(h)){f(h,!1);try{await M("stop_tts")}catch(it){console.error("Failed to stop TTS:",it)}}f(U,!0),f(v,null),y();let R="TTS",ge=null;e().tts.engine==="piper"?(R="Piper",ge=e().tts.voice):e().tts.engine==="pocket_tts"?(R="Pocket-TTS",ge=e().tts.pocket_tts.voice):e().tts.engine==="espeak"&&(R="eSpeak-NG",ge=null);const we=`Hi this is ${R} speaking from VoxCtrl`;try{await M("speak_text",{text:we,voice:ge})}catch(it){f(v,`${it}`),clearInterval(u),f(c,!1),f(U,!1)}}let w=W(!1);function X(){return!e().tts.enabled||a(w)?!0:a(h)?!1:a(U)?!0:e().tts.engine==="piper"?a(S)||a(D)||!a(x)[e().tts.voice]:e().tts.engine==="pocket_tts"?a(q)||a(Z)||!a(E):!1}let V=W(Ue([])),N=W(null);async function F(){try{f(V,await M("list_pocket_tts_voices",{voiceDir:e().tts.pocket_tts.voice_dir}),!0)}catch(R){console.error("list_pocket_tts_voices:",R)}}async function se(){const R=e().tts.pocket_tts.voice_dir;if(!R){f(N,null),await F();return}const ge=await M("check_directory_exists",{path:R});f(N,ge?null:"This folder does not exist. Please create it first or leave blank for the default location.",!0),a(N)||await F()}function j(){n()}function I(R){R.key==="Enter"&&R.currentTarget.blur()}let re=he(()=>C.map(R=>({value:R,label:`${R}${a(x)[R]?" ✔":""}`}))),ve=he(()=>a(V).map(R=>({value:R.id,label:R.label})));const le=[{value:"pocket_tts",label:"Pocket-TTS (neural, voice cloning)"},{value:"piper",label:"Piper (neural, high quality)"},{value:"espeak",label:"eSpeak-NG (lightweight)"}];let E=W(!1),q=W(!1),Z=W(!1);async function ue(){f(q,!0);try{f(E,await M("check_pocket_tts_ready",{voice:e().tts.pocket_tts.voice,voiceDir:e().tts.pocket_tts.voice_dir}),!0)}catch(R){console.error("check_pocket_tts_ready:",R),f(E,!1)}finally{f(q,!1)}}async function ie(){if(!a(Z)){f(Z,!0);try{await M("download_pocket_tts",{voice:e().tts.pocket_tts.voice,voiceDir:e().tts.pocket_tts.voice_dir,hfToken:e().tts.pocket_tts.hf_token}),f(E,!0)}catch(R){alert(`Failed to download Pocket-TTS assets: ${R}`)}finally{f(Z,!1)}}}function ne(){n(),f(E,!1),ue()}function _e(){n()}async function Ie(){n(),f(w,!0);try{e().tts.engine==="pocket_tts"?(f(E,!1),await F(),await ue()):e().tts.engine==="piper"&&(e().tts.voice_dir?await L():await z())}finally{setTimeout(()=>{f(w,!1)},400)}}ut(async()=>{e().tts.voice_dir?L():z(),e().tts.engine==="pocket_tts"&&(await F(),ue()),d=await yt("tts-playback-start",()=>{a(c)&&(clearInterval(u),f(i,a(l),!0),f(c,!1)),f(U,!1),f(h,!0)}),p=await yt("tts-playback-end",()=>{f(h,!1)}),_=await yt("tts-error",R=>{f(v,R.payload,!0),clearInterval(u),f(c,!1),f(i,null),f(U,!1),f(h,!1)})}),Qr(()=>{u&&clearInterval(u),d&&d(),p&&p(),_&&_()});let P=W(!1),K=W(Ue([]));function $(R,ge){const we=ge.toUpperCase();return R==="Control"?"KEY_LEFTCTRL":R==="Alt"?"KEY_LEFTALT":R==="Shift"?"KEY_LEFTSHIFT":R==="Meta"||R==="OS"||R==="Super"?"KEY_LEFTMETA":we==="SPACE"?"KEY_SPACE":we==="ENTER"?"KEY_ENTER":we==="ESCAPE"||we==="ESC"?"KEY_ESC":we==="TAB"?"KEY_TAB":we==="BACKSPACE"?"KEY_BACKSPACE":we==="DELETE"?"KEY_DELETE":we.startsWith("KEY")?we:we.startsWith("DIGIT")?`KEY_${we.replace("DIGIT","")}`:we.startsWith("ARROW")?`KEY_${we.replace("ARROW","")}`:we.startsWith("F")&&we.length>1?`KEY_${we}`:R.length===1?`KEY_${R.toUpperCase()}`:`KEY_${we}`}function ce(R){if(!a(P))return;R.preventDefault(),R.stopPropagation();const ge=$(R.key,R.code);a(K).includes(ge)||f(K,[...a(K),ge],!0),R.key==="Escape"&&(e(e().tts.stop_key=[...a(K)],!0),n(),f(K,[],!0),f(P,!1))}function O(R){a(P)&&(R.preventDefault(),R.stopPropagation(),a(K).length>0&&(e(e().tts.stop_key=[...a(K)],!0),n()),f(K,[],!0),f(P,!1))}function A(){a(K).length>0&&(e(e().tts.stop_key=[...a(K)],!0),n(),f(K,[],!0)),f(P,!1)}var te=vd(),Se=r(o(te),2),et=r(o(Se),2),je=r(o(et),2),He=r(et,2),Ae=r(o(He),2);wt(Ae,{get options(){return le},onchange:Ie,get value(){return e().tts.engine},set value(R){e(e().tts.engine=R,!0)}});var Q=r(He,2);{var pe=R=>{var ge=Gu(),we=Ot(ge),it=r(o(we),2);H("change",it,n),st(it,()=>e().tts.gpu,It=>e(e().tts.gpu=It,!0)),g(R,ge)};B(Q,R=>{e().tts.engine==="piper"&&R(pe)})}var Pe=r(Q,2),Be=o(Pe),Ze=o(Be),ft=r(Be,2),at=r(Pe,2),tt=o(at),Ke=o(tt),$e=r(tt,2);{var We=R=>{var ge=Ju(),we=r(o(ge),2);let it;var It=o(we);J(()=>{it=ye(we,1,"run-speed-value svelte-1q9seip",null,it,{counting:a(c)}),ee(It,a(c)?`${a(l)} ms`:`${a(i)} ms`)}),g(R,ge)};B($e,R=>{(a(c)||a(i)!==null)&&R(We)})}var dt=r(at,2);{var nt=R=>{var ge=Xu(),we=o(ge);J(()=>{var it;return ee(we,`❌ ${(it=a(v))!=null?it:""}`)}),g(R,ge)};B(dt,R=>{a(v)&&R(nt)})}var Rt=r(Se,2);{var vt=R=>{var ge=sd(),we=r(o(ge),2),it=r(o(we),2);wt(it,{get options(){return a(re)},onchange:oe,get value(){return e().tts.voice},set value(Oe){e(e().tts.voice=Oe,!0)}});var It=r(we,2),Jt=o(It);{var gs=Oe=>{var qe=Zu();g(Oe,qe)},Rs=Oe=>{var qe=Qu(),ke=o(qe);J(()=>{var rt;return ee(ke,`⏳ Downloading ${(rt=e().tts.voice)!=null?rt:""} (model + config)...`)}),g(Oe,qe)},Ys=Oe=>{var qe=ed(),ke=o(qe),rt=o(ke),Tt=r(ke,2),Xt=o(Tt);J(()=>{ye(ke,1,fs(a(x)[e().tts.voice]?"status-downloaded":"status-missing"),"svelte-1q9seip"),ee(rt,a(x)[e().tts.voice]?"✔ Voice downloaded and ready":"❌ Voice files missing"),Tt.disabled=a(x)[e().tts.voice]||a(D),ee(Xt,a(x)[e().tts.voice]?"Downloaded":"📥 Download")}),H("click",Tt,()=>b(e().tts.voice)),g(Oe,qe)};B(Jt,Oe=>{a(S)?Oe(gs):a(D)?Oe(Rs,1):Oe(Ys,-1)})}var me=r(It,2),Me=r(o(me),2);let Ne;var Ge=r(Me,2);{var Mt=Oe=>{var qe=td(),ke=o(qe);J(()=>ee(ke,a(Y))),g(Oe,qe)};B(Ge,Oe=>{a(Y)&&Oe(Mt)})}J(()=>Ne=ye(Me,1,"svelte-1q9seip",null,Ne,{"field-input-error":!!a(Y)})),H("change",Me,G),Ms("blur",Me,L),H("keydown",Me,ae),be(Me,()=>e().tts.voice_dir,Oe=>e(e().tts.voice_dir=Oe,!0)),g(R,ge)};B(Rt,R=>{e().tts.engine==="piper"&&R(vt)})}var Pt=r(Rt,2);{var Gt=R=>{var ge=ld(),we=r(o(ge),2),it=r(o(we),2);wt(it,{get options(){return a(ve)},onchange:ne,get value(){return e().tts.pocket_tts.voice},set value(ke){e(e().tts.pocket_tts.voice=ke,!0)}});var It=r(we,2),Jt=o(It);{var gs=ke=>{var rt=ad();g(ke,rt)},Rs=ke=>{var rt=nd();g(ke,rt)},Ys=ke=>{var rt=id(),Tt=o(rt),Xt=o(Tt),Qe=r(Tt,2),Re=o(Qe);J(()=>{ye(Tt,1,fs(a(E)?"status-downloaded":"status-missing"),"svelte-1q9seip"),ee(Xt,a(E)?"✔ Model and voice clip downloaded and ready":"❌ Model files missing"),Qe.disabled=a(E)||a(Z),ee(Re,a(E)?"Downloaded":"📥 Download")}),H("click",Qe,ie),g(ke,rt)};B(Jt,ke=>{a(q)?ke(gs):a(Z)?ke(Rs,1):ke(Ys,-1)})}var me=r(It,2),Me=r(o(me),2),Ne=r(me,4),Ge=r(o(Ne),2);let Mt;var Oe=r(Ge,2);{var qe=ke=>{var rt=rd(),Tt=o(rt);J(()=>ee(Tt,a(N))),g(ke,rt)};B(Oe,ke=>{a(N)&&ke(qe)})}J(()=>Mt=ye(Ge,1,"svelte-1q9seip",null,Mt,{"field-input-error":!!a(N)})),H("change",Me,_e),be(Me,()=>e().tts.pocket_tts.hf_token,ke=>e(e().tts.pocket_tts.hf_token=ke,!0)),H("change",Ge,j),Ms("blur",Ge,se),H("keydown",Ge,I),be(Ge,()=>e().tts.pocket_tts.voice_dir,ke=>e(e().tts.pocket_tts.voice_dir=ke,!0)),g(R,ge)};B(Pt,R=>{e().tts.engine==="pocket_tts"&&R(Gt)})}var Ss=r(Pt,2),kt=r(o(Ss),2),Ye=r(o(kt),2),cs=r(kt,2),Dt=r(o(cs),4),Le=o(Dt);{var pt=R=>{var ge=od(),we=r(o(ge),2),it=o(we);J(It=>ee(it,It),[()=>a(K).length>0?a(K).join(" + ").replace(/KEY_/g,""):"Press your physical shortcut combination now..."]),g(R,ge)},Bt=R=>{var ge=dd(),we=o(ge);{var it=Jt=>{var gs=ud(),Rs=Ot(gs);bt(Rs,21,()=>e().tts.stop_key,gt,(Ys,me)=>{var Me=cd(),Ne=o(Me);J(Ge=>ee(Ne,Ge),[()=>a(me).replace("KEY_","")]),g(Ys,Me)}),g(Jt,gs)},It=Jt=>{var gs=Ee("⚠️ Click/Focus here to press a stop key!");g(Jt,gs)};B(we,Jt=>{e().tts.stop_key.length>0?Jt(it):Jt(It,-1)})}g(R,ge)};B(Le,R=>{a(P)?R(pt):R(Bt,-1)})}J((R,ge,we)=>{ee(Ze,`Speed (${R!=null?R:""}×)`),tt.disabled=ge,ee(Ke,a(U)?"Speaking...":a(h)?"⏹ Stop & Test":"Test TTS"),ye(Dt,1,we,"svelte-1q9seip")},[()=>e().tts.speed.toFixed(2),()=>X(),()=>fs(["border-2 rounded-desktop p-6 text-center cursor-pointer outline-none transition-all duration-200 flex flex-col items-center justify-center min-h-[80px]",a(P)?"border-solid border-[#f43f5e] bg-[rgba(244,63,94,0.05)] animate-border-pulse":"border-dashed border-white/5 bg-black/25 hover:border-accent-blue hover:bg-black/35 focus:border-accent-blue focus:bg-black/35"].join(" "))]),H("change",je,n),st(je,()=>e().tts.enabled,R=>e(e().tts.enabled=R,!0)),H("change",ft,n),be(ft,()=>e().tts.speed,R=>e(e().tts.speed=R,!0)),H("click",tt,de),H("change",Ye,n),st(Ye,()=>e().tts.response_overlay,R=>e(e().tts.response_overlay=R,!0)),H("click",Dt,()=>f(P,!0)),Ms("focus",Dt,()=>f(P,!0)),Ms("blur",Dt,A),H("keydown",Dt,ce),H("keyup",Dt,O),g(s,te),Xe()}Vt(["change","click","keydown","keyup"]);var fd=T(''),hd=T(`⚠️ The model isn't available on this server. Post-processing will fail with a 404 — pick a model from the list above or pull it on the server.`),_d=T(" "),gd=T('Select the Custom preset to edit the system and user prompts.'),bd=T('⚠️ The user prompt must contain the placeholder.'),md=T('Use where your dictated speech should be inserted.'),yd=T(`

OpenAI API LLM Post-Processing

Connect to any OpenAI-compatible API server — a local server or a hosted + provider. The URL defaults to a local server; point it anywhere you like and + supply an API key when the server requires one.

Connection

Default Prompts

The system prompt tells the model how to transform your speech. The user + prompt is the message sent to the model — it must contain , which is replaced with whatever you dictate. + Built-in presets are read-only; choose Custom to edit the + prompts yourself.

System Prompt
User Prompt
`);function wd(s,t){Je(t,!0);let e=Ve(t,"cfg",15);function n(){Es.set(!0)}let i=W(!1),l=W(null),c=W(Ue([])),u=he(()=>[...a(c).map(P=>({value:P,label:P})),...e().openai.model&&!a(c).includes(e().openai.model)?[{value:e().openai.model,label:`${e().openai.model} (not found)`}]:[]]);const d=[{value:"clean",label:"Clean (grammar fix)"},{value:"formal",label:"Formal"},{value:"casual",label:"Casual"},{value:"bullet",label:"Bullet points"},{value:"concise",label:"Concise (summarize)"},{value:"custom",label:"Custom (editable)"}],p={clean:"Fix grammar and punctuation only. Return only the corrected text, no commentary.",formal:"Rewrite the user's text in formal professional language. Return only the result.",casual:"Rewrite the user's text in casual conversational language. Return only the result.",bullet:"Convert the user's text to a bullet-point list. Return only the list.",concise:"Summarize the user's text concisely in 1-2 sentences. Return only the summary."};let _=he(()=>e().openai.mode==="custom");function h(){const P=p[e().openai.mode];P!==void 0&&(e(e().openai.system_prompt=P,!0),e(e().openai.user_prompt="{text}",!0)),n()}let v=he(()=>e().openai.user_prompt.includes("{text}")),k=he(()=>a(c).length>0&&!!e().openai.model&&!a(c).includes(e().openai.model));async function y(){f(i,!0),f(l,null);try{const P=await M("test_openai",{endpoint:e().openai.endpoint,apiKey:e().openai.api_key,timeoutSecs:e().openai.timeout_secs});f(l,{success:P.success,message:P.message},!0),P.success&&(f(c,P.models,!0),!e().openai.model&&P.models.length>0&&(e(e().openai.model=P.models[0],!0),n()))}catch(P){f(l,{success:!1,message:P.toString()},!0)}finally{f(i,!1)}}ut(()=>{y()});var C=yd(),x=r(o(C),4),S=r(o(x),2),D=r(o(S),2),U=r(S,2),Y=r(o(U),2),z=r(U,2),b=r(o(z),2);{var L=P=>{wt(P,{get options(){return a(u)},onchange:n,get value(){return e().openai.model},set value(K){e(e().openai.model=K,!0)}})},G=P=>{var K=fd();H("change",K,n),be(K,()=>e().openai.model,$=>e(e().openai.model=$,!0)),g(P,K)};B(b,P=>{a(c).length>0?P(L):P(G,-1)})}var ae=r(z,2);{var oe=P=>{var K=hd(),$=r(o(K)),ce=o($);J(()=>ee(ce,e().openai.model)),g(P,K)};B(ae,P=>{a(k)&&P(oe)})}var de=r(ae,2),w=r(o(de),2),X=r(de,2),V=o(X),N=o(V),F=r(V,2);{var se=P=>{var K=_d(),$=o(K);J(()=>{ye(K,1,`status-msg ${a(l).success?"success":"error"}`,"svelte-1bvctpo"),ee($,a(l).message)}),g(P,K)};B(F,P=>{a(l)&&P(se)})}var j=r(x,2),I=r(o(j),2),re=r(o(I));re.textContent="{text}";var ve=r(I,2),le=r(o(ve),2);wt(le,{get options(){return d},onchange:h,get value(){return e().openai.mode},set value(P){e(e().openai.mode=P,!0)}});var E=r(ve,2),q=r(o(E),2),Z=r(E,2),ue=r(o(Z),2);mt(ue,"placeholder","{text}");var ie=r(ue,2);{var ne=P=>{var K=gd();g(P,K)},_e=P=>{var K=bd(),$=r(o(K));$.textContent="{text}",g(P,K)},Ie=P=>{var K=md(),$=r(o(K));$.textContent="{text}",g(P,K)};B(ie,P=>{a(_)?a(v)?P(Ie,-1):P(_e,1):P(ne)})}J(()=>{V.disabled=a(i),ee(N,a(i)?"⏳ Testing...":"🔌 Test Connection"),q.readOnly=!a(_),ye(q,1,fs(a(_)?"":"locked"),"svelte-1bvctpo"),ue.readOnly=!a(_),ye(ue,1,fs(a(_)?a(v)?"":"invalid":"locked"),"svelte-1bvctpo")}),H("change",D,n),be(D,()=>e().openai.endpoint,P=>e(e().openai.endpoint=P,!0)),H("change",Y,n),be(Y,()=>e().openai.api_key,P=>e(e().openai.api_key=P,!0)),H("change",w,n),be(w,()=>e().openai.timeout_secs,P=>e(e().openai.timeout_secs=P,!0)),H("click",V,y),H("change",q,n),be(q,()=>e().openai.system_prompt,P=>e(e().openai.system_prompt=P,!0)),H("change",ue,n),be(ue,()=>e().openai.user_prompt,P=>e(e().openai.user_prompt=P,!0)),g(s,C),Xe()}Vt(["change","click"]);var xd=T('
'),kd=T('

No snippets defined.

'),Td=T('

Features & Post-Processing

Text cleanup

Custom Dictionary

Provide a comma-separated list of words (e.g. names or jargon like "Waylin, Rufer, Enola, Kenz") that are hard to spell. The transcription process will correct these in the final text.

Snippets

Type a trigger word → it expands to the replacement text.

');function Ed(s,t){Je(t,!0);let e=Ve(t,"cfg",15);function n(){Es.set(!0)}let i=W(Ue(Object.entries(e().features.snippets).map(([w,X])=>({key:w,val:X}))));function l(){const w={};for(const{key:X,val:V}of a(i))X.trim()&&(w[X.trim()]=V.trim());e(e().features.snippets=w,!0),n()}function c(){f(i,[...a(i),{key:"",val:""}],!0)}function u(w){f(i,a(i).filter((X,V)=>V!==w),!0),l()}let d=he(()=>e().features.custom_vocabulary?e().features.custom_vocabulary.join(", "):"");function p(w){const X=w.target;e(e().features.custom_vocabulary=X.value.split(",").map(V=>V.trim()).filter(V=>V.length>0),!0),n()}function _(w){function X(){w.style.height="auto",w.style.height=`${w.scrollHeight}px`}w.addEventListener("input",X);const V=setTimeout(X,0);return{update(){X()},destroy(){clearTimeout(V),w.removeEventListener("input",X)}}}var h=Td(),v=r(o(h),2),k=r(o(v),2),y=r(o(k),2),C=r(k,2),x=r(o(C),2),S=r(C,2),D=r(o(S),2),U=r(v,2),Y=r(o(U),4);ua(Y,w=>_==null?void 0:_(w));var z=r(U,2),b=o(z),L=r(o(b),2),G=r(b,2),ae=o(G);bt(ae,17,()=>a(i),gt,(w,X,V)=>{var N=xd(),F=o(N),se=r(F,4),j=r(se,2);H("input",F,l),be(F,()=>a(i)[V].key,I=>a(i)[V].key=I),H("input",se,l),be(se,()=>a(i)[V].val,I=>a(i)[V].val=I),H("click",j,()=>u(V)),g(w,N)});var oe=r(ae,2);{var de=w=>{var X=kd();g(w,X)};B(oe,w=>{a(i).length===0&&w(de)})}J(()=>Go(Y,a(d))),H("change",y,n),st(y,()=>e().features.remove_fillers,w=>e(e().features.remove_fillers=w,!0)),H("change",x,n),st(x,()=>e().features.spoken_punctuation,w=>e(e().features.spoken_punctuation=w,!0)),H("change",D,n),st(D,()=>e().features.auto_format_lists,w=>e(e().features.auto_format_lists=w,!0)),H("input",Y,p),H("click",L,c),g(s,h),Xe()}Vt(["change","input","click"]);class Ja extends nc{constructor(t){super(t)}static async new(t,e,n){return M("plugin:image|new",{rgba:Dn(t),width:e,height:n}).then(i=>new Ja(i))}static async fromBytes(t){return M("plugin:image|from_bytes",{bytes:Dn(t)}).then(e=>new Ja(e))}static async fromPath(t){return M("plugin:image|from_path",{path:t}).then(e=>new Ja(e))}async rgba(){return M("plugin:image|rgba",{rid:this.rid}).then(t=>new Uint8Array(t))}async size(){return M("plugin:image|size",{rid:this.rid})}}function Dn(s){return s==null?null:typeof s=="string"?s:s instanceof Ja?s.rid:s}var Ji;(function(s){s.Nsis="nsis",s.Msi="msi",s.Deb="deb",s.Rpm="rpm",s.AppImage="appimage",s.App="app"})(Ji||(Ji={}));async function Sd(){return M("plugin:app|version")}const Ad="/assets/voxctrl-CDHFw5hI.gif";var Cd=T(`

About VoxCtrl

VoxCtrl

Native, on-device voice-to-text for Linux and Windows. + Uses whisper.cpp and Moonshine for offline transcription and routes speech to any destination.

System

FrontendSvelte 5 + Tauri 2
BackendRust (Tokio async)
Inferencewhisper.cpp & Moonshine
Config~/.config/voxctrl/
Models~/.local/share/voxctrl/models/
MCP socket/tmp/voxctrl-mcp.sock

Open Source Attributions

This application is built possible by these outstanding open-source projects:

whisper.cpp MIT License
Tauri Framework MIT / Apache 2.0
Svelte & Vite MIT License
Piper TTS MIT License
Pocket-TTS (Kyutai Labs) MIT / Apache 2.0
Candle MIT / Apache 2.0
whisper-rs MIT License
Rust, Tokio & CPAL MIT / Apache 2.0
`);function Pd(s,t){Je(t,!0);let e=W("0.1.0");ut(async()=>{try{f(e,await Sd(),!0)}catch(p){console.error("Failed to fetch app version:",p)}});var n=Cd(),i=r(o(n),2),l=o(i),c=r(l,2),u=r(o(c),2),d=o(u);J(()=>{var p;mt(l,"src",Ad),ee(d,`Version ${(p=a(e))!=null?p:""} — Rust + Tauri Edition`)}),g(s,n),Xe()}var Md=T(''),Od=T(''),Dd=T(' 🛑 Stop',1),Id=T('🎙️ Record'),Ld=T('
Unsaved changes detected
'),Nd=T('
');function Rd(s,t){Je(t,!0);const e=()=>St(Yt,"$config",l),n=()=>St(Ct,"$status",l),i=()=>St(Es,"$configDirty",l),[l,c]=_s();let u=W("general");const d=[{id:"general",label:"General",icon:"⚙️"},{id:"engine",label:"Engine",icon:"🧠"},{id:"hotkeys",label:"Hotkeys",icon:"⌨️"},{id:"targets",label:"Output Targets",icon:"🎯"},{id:"visual",label:"Visual",icon:"🎨"},{id:"audio",label:"Audio",icon:"🔊"},{id:"tts",label:"TTS",icon:"🗣️"},{id:"features",label:"Features",icon:"✨"},{id:"openai",label:"OpenAI API",icon:"🤖"},{id:"about",label:"About",icon:"ℹ️"}];async function p(){await nl(e())}async function _(){await M("toggle_recording")}let h=a(u),v=W(null);ka(()=>{var K,$;const P=a(u);P!==h&&(h=P,a(v)&&(a(v).scrollTop=0),($=(K=e())==null?void 0:K.audio)!=null&&$.dynamic_stream&&n().recording&&M("stop_recording").catch(ce=>{console.error("Failed to stop recording on activeTab change:",ce)}))}),ut(()=>{let P;P=fi.subscribe(K=>{if(K){const $=e();if($&&$.engine&&$.engine.whisper_cpp){const ce=$.engine.whisper_cpp.model_size;$.engine.backend!=="moonshine"&&M("check_model_downloaded",{modelSize:ce}).then(async O=>{if(!O){f(u,"engine");try{const{getCurrentWindow:A}=await Qo(async()=>{const{getCurrentWindow:Se}=await Promise.resolve().then(()=>Tv);return{getCurrentWindow:Se}},void 0),te=A();await te.show(),await te.setFocus()}catch(A){console.error("Failed to programmatically show settings window on startup:",A)}}}).catch(O=>{console.error("Failed to check model download status on startup:",O)})}P?P():setTimeout(()=>P(),0)}})});var k=Nd(),y=o(k),C=o(y),x=o(C),S=r(C,2);bt(S,21,()=>d,gt,(P,K)=>{var $=Od();let ce;var O=o($),A=o(O),te=r(O,2),Se=o(te),et=r(te,2);{var je=He=>{var Ae=Md();g(He,Ae)};B(et,He=>{a(u)===a(K).id&&He(je)})}J(()=>{ce=ye($,1,"nav-btn svelte-myrvk6",null,ce,{active:a(u)===a(K).id}),ee(A,a(K).icon),ee(Se,a(K).label)}),H("click",$,()=>f(u,a(K).id,!0)),g(P,$)});var D=r(S,2),U=o(D);let Y;var z=o(U),b=o(z),L=r(o(b),2),G=o(L),ae=r(b,2),oe=o(ae),de=r(z,2);let w;var X=o(de);{var V=P=>{var K=Dd();g(P,K)},N=P=>{var K=Id();g(P,K)};B(X,P=>{n().recording?P(V):P(N,-1)})}var F=r(y,2),se=o(F),j=o(se);{var I=P=>{fc(P,{get cfg(){return Xs(),e()},set cfg(K){Js(Yt,K)}})},re=P=>{Rc(P,{get cfg(){return Xs(),e()},set cfg(K){Js(Yt,K)}})},ve=P=>{Nu(P,{})},le=P=>{Yu(P,{})},E=P=>{yc(P,{get cfg(){return Xs(),e()},set cfg(K){Js(Yt,K)}})},q=P=>{qc(P,{get cfg(){return Xs(),e()},set cfg(K){Js(Yt,K)}})},Z=P=>{pd(P,{get cfg(){return Xs(),e()},set cfg(K){Js(Yt,K)}})},ue=P=>{Ed(P,{get cfg(){return Xs(),e()},set cfg(K){Js(Yt,K)}})},ie=P=>{wd(P,{get cfg(){return Xs(),e()},set cfg(K){Js(Yt,K)}})},ne=P=>{Pd(P,{})};B(j,P=>{a(u)==="general"?P(I):a(u)==="engine"?P(re,1):a(u)==="hotkeys"?P(ve,2):a(u)==="targets"?P(le,3):a(u)==="visual"?P(E,4):a(u)==="audio"?P(q,5):a(u)==="tts"?P(Z,6):a(u)==="features"?P(ue,7):a(u)==="openai"?P(ie,8):a(u)==="about"&&P(ne,9)})}sl(se,P=>f(v,P),()=>a(v));var _e=r(se,2);{var Ie=P=>{var K=Ld(),$=r(o(K),2);H("click",$,p),g(P,K)};B(_e,P=>{i()&&P(Ie)})}J(()=>{var P;mt(x,"src",ec),Y=ye(U,1,"status-panel svelte-myrvk6",null,Y,{recording:n().recording,speaking:n().speaking}),ee(G,n().recording?"Recording":n().speaking?"Speaking":"Idle"),ee(oe,`${(P=n().word_count)!=null?P:""} words`),w=ye(de,1,"btn-record svelte-myrvk6",null,w,{active:n().recording})}),H("click",de,_),g(s,k),Xe(),c()}Vt(["click"]);var Fd=T(""),zd=T('
'),Wd=T('
VOXCTRL VOICE CARD
TARGET •••• VOX
');function qd(s,t){Je(t,!0);const e=()=>St(Ct,"$status",n),[n,i]=_s();let l=Ve(t,"recording",3,!1);Ve(t,"speaking",3,!1);let c=Ve(t,"active",3,!0);const u=20,d=6;let p=W(Ue(Array(u).fill(0))),_=null,h,v=0,k=0;const y=he(()=>e().audio_ready!==!1),C=he(()=>e().active_target_label||"Focused Window");ut(()=>{yt("audio-level",j=>{v=Math.min(1,j.payload*100)}).then(j=>{_=j});let N=0;const F=new Float32Array(u);function se(){N+=.016,k+=(v-k)*.35,v*=.86;for(let j=0;jF[j]?I:F[j]*.86}f(p,Array.from(F),!0),h=requestAnimationFrame(se)}return h=requestAnimationFrame(se),()=>{_&&_(),cancelAnimationFrame(h)}});function x(N){return N===0?"red":N<=2?"amber":"green"}var S=Wd();let D;var U=o(S);let Y;var z=r(o(U),8),b=r(o(z),2);{var L=N=>{var F=Ee("PROC");g(N,F)},G=N=>{var F=Ee("INIT");g(N,F)},ae=N=>{var F=Ee("REC");g(N,F)};B(b,N=>{e().processing?N(L):l()&&!a(y)?N(G,1):N(ae,-1)})}var oe=r(z,2);bt(oe,21,()=>a(p),gt,(N,F)=>{var se=zd();bt(se,21,()=>Array(d),gt,(j,I,re)=>{var ve=Fd();let le;J(E=>le=ye(ve,1,`dot ${E!=null?E:""}`,"svelte-1pt4ba2",le,{lit:d-re<=a(F)*d}),[()=>x(re)]),g(j,ve)}),g(N,se)});var de=r(oe,4),w=o(de);{var X=N=>{var F=Ee("Reading the card…");g(N,F)},V=N=>{var F=Ee();J(()=>ee(F,a(C))),g(N,F)};B(w,N=>{e().processing?N(X):N(V,-1)})}J(()=>{D=ye(S,1,"card-scene svelte-1pt4ba2",null,D,{on:c()}),Y=ye(U,1,"card svelte-1pt4ba2",null,Y,{processing:e().processing,initializing:l()&&!a(y)})}),g(s,S),Xe(),i()}var Vd=T('
'),Bd=T('
WAVEFORM // OSC-01 TGT ▸
');function Ud(s,t){Je(t,!0);const e=()=>St(Ct,"$status",n),[n,i]=_s();let l=Ve(t,"recording",3,!1),c=Ve(t,"active",3,!0);const u=126,d=500,p=78;let _=W(""),h=null,v,k=0,y=0;const C=he(()=>e().audio_ready!==!1),x=he(()=>e().active_target_label||"Focused Window");ut(()=>{yt("audio-level",ve=>{k=Math.min(1,ve.payload*100)}).then(ve=>{h=ve});const j=new Float32Array(u);let I=0;function re(){I+=.016,y+=(k-y)*.35,k*=.86;let ve=0;if(e().processing)ve=.55*Math.sin(I*9)*(.6+.4*Math.sin(I*1.7));else if(l()&&e().audio_ready===!1)ve=.05*(Math.random()*2-1);else if(l()){const E=Math.random()*2-1;ve=Math.min(1,y*1.5)*(.45*Math.sin(I*24)+.55*E)}j.copyWithin(0,1),j[u-1]=ve;let le="";for(let E=0;E{h&&h(),cancelAnimationFrame(v)}});var S=Bd();let D;var U=o(S),Y=o(U),z=r(o(Y),4),b=o(z);{var L=j=>{var I=Ee("· TRANSCRIBING");g(j,I)},G=j=>{var I=Ee("· CALIBRATING");g(j,I)},ae=j=>{var I=Ee("· LIVE TRACE");g(j,I)};B(b,j=>{e().processing?j(L):l()&&!a(C)?j(G,1):j(ae,-1)})}var oe=r(z,4),de=r(o(oe),2),w=o(de),X=r(Y,2),V=r(o(X),6);bt(V,16,()=>[1,2,3,4],gt,(j,I)=>{var re=Vd();J(()=>$s(re,`left: ${I*20}%`)),g(j,re)});var N=r(V,2);mt(N,"viewBox","0 0 500 78");var F=o(N),se=r(F);J(()=>{D=ye(S,1,"scope svelte-xjziu1",null,D,{on:c(),processing:e().processing,initializing:l()&&!a(C)}),ee(w,a(x)),mt(F,"d",a(_)),mt(se,"d",a(_))}),g(s,S),Xe(),i()}var jd=T('
');function Hd(s,t){Je(t,!0);const e=()=>St(Ct,"$status",n),[n,i]=_s();let l=Ve(t,"recording",3,!1),c=Ve(t,"active",3,!0),u=W(0),d=null,p,_=0,h=0;const v=he(()=>e().audio_ready!==!1),k=he(()=>e().active_target_label||"Focused Window");ut(()=>{yt("audio-level",X=>{_=Math.min(1,X.payload*100)}).then(X=>{d=X});function w(){h+=(_-h)*.35,_*=.86,f(u,h,!0),p=requestAnimationFrame(w)}return p=requestAnimationFrame(w),()=>{d&&d(),cancelAnimationFrame(p)}});var y=jd();let C;var x=r(o(y),2),S=r(o(x),2),D=o(S),U=o(D);{var Y=w=>{var X=Ee("PULSE // ANALYZING");g(w,X)},z=w=>{var X=Ee("PULSE // ACQUIRING");g(w,X)},b=w=>{var X=Ee("PULSE // TARGET LOCK");g(w,X)};B(U,w=>{e().processing?w(Y):l()&&!a(v)?w(z,1):w(b,-1)})}var L=r(D,2),G=o(L);{var ae=w=>{var X=Ee("Decoding transmission…");g(w,X)},oe=w=>{var X=Ee("Connecting mic…");g(w,X)},de=w=>{var X=Ee();J(()=>ee(X,a(k))),g(w,X)};B(G,w=>{e().processing?w(ae):l()&&!a(v)?w(oe,1):w(de,-1)})}J(()=>{var w;C=ye(y,1,"radar svelte-13tl5wx",null,C,{on:c(),processing:e().processing,initializing:l()&&!a(v)}),$s(y,`--lvl: ${(w=a(u))!=null?w:""}`)}),g(s,y),Xe(),i()}var Kd=T('
'),$d=T('
OCEAN WAVE
');function Yd(s,t){Je(t,!0);const e=()=>St(Ct,"$status",n),[n,i]=_s();let l=Ve(t,"recording",3,!1);Ve(t,"speaking",3,!1);let c=Ve(t,"active",3,!0);const u=380,d=90;let p=W(""),_=W(""),h=W(""),v=W(60),k=null,y,C=0,x=0;const S=he(()=>e().audio_ready!==!1),D=he(()=>e().active_target_label||"Focused Window");function U(E,q,Z,ue){let ie=`M 0 ${d} L 0 ${ue.toFixed(1)}`;for(let ne=0;ne<=u;ne+=8){const _e=ue+Math.sin(ne*q+Z)*E;ie+=` L ${ne} ${_e.toFixed(1)}`}return ie+` L ${u} ${d} Z`}ut(()=>{yt("audio-level",Z=>{C=Math.min(1,Z.payload*100)}).then(Z=>{k=Z});let E=0;function q(){E+=.016,x+=(C-x)*.35,C*=.86;const Z=x,ue=e().processing?4+2.5*Math.sin(E*1.6):0,ie=64-Z*20-ue,ne=56-Z*24-ue*1.2,_e=47-Z*28-ue*1.4,Ie=(e().processing?5:2.5)+Z*14,P=(e().processing?6:2)+Z*18,K=(e().processing?7:1.5)+Z*22;f(p,U(Ie,.014,E*2.1,ie),!0),f(_,U(P,.022,-E*3,ne),!0),f(h,U(K,.018,E*3.9,_e),!0),f(v,38+_e-21+Math.sin(E*2.2)*2.5),y=requestAnimationFrame(q)}return y=requestAnimationFrame(q),()=>{k&&k(),cancelAnimationFrame(y)}});var Y=$d();let z;var b=r(o(Y),4),L=o(b);{var G=E=>{var q=Ee("deep current — processing");g(E,q)},ae=E=>{var q=Ee("low tide — preparing");g(E,q)},oe=E=>{var q=Ee("high tide — listening");g(E,q)};B(L,E=>{e().processing?E(G):l()&&!a(S)?E(ae,1):E(oe,-1)})}var de=r(b,2),w=o(de);mt(w,"viewBox","0 0 380 90");var X=o(w),V=r(X),N=r(V),F=r(de,2);bt(F,16,()=>[0,1,2],gt,(E,q)=>{var Z=Kd();J(()=>$s(Z,`left: ${64+q*112}px; animation-delay: ${q*1.4}s;`)),g(E,Z)});var se=r(F,2),j=r(o(se),2),I=o(j);{var re=E=>{var q=Ee("Sounding the depths…");g(E,q)},ve=E=>{var q=Ee("Casting off…");g(E,q)},le=E=>{var q=Ee();J(()=>ee(q,a(D))),g(E,q)};B(I,E=>{e().processing?E(re):l()&&!a(S)?E(ve,1):E(le,-1)})}J(()=>{var E;z=ye(Y,1,"ocean svelte-1orgnnz",null,z,{on:c(),processing:e().processing}),mt(X,"d",a(p)),mt(V,"d",a(_)),mt(N,"d",a(h)),$s(se,`top: ${(E=a(v))!=null?E:""}px;`)}),g(s,Y),Xe(),i()}var Gd=T("
"),Jd=T('
');function Xd(s,t){Je(t,!0);const e=()=>St(Ct,"$status",n),[n,i]=_s();let l=Ve(t,"recording",3,!1),c=Ve(t,"active",3,!0);const u=5,d=8,p=52;let _=W(Ue(Array(u).fill(d))),h=null,v,k=0,y=0;const C=he(()=>e().audio_ready!==!1),x=he(()=>e().active_target_label||"Focused Window");function S(N,F,se,j,I,re,ve,le){const E=(F-1)/2,q=1-Math.abs(N-E)/(E+1)*.4;let Z;if(re)Z=(Math.sin(j*4-N*.85)*.5+.5)*q;else if(I&&!ve)Z=0;else if(I){const ue=Math.sin(j*3-N*.8);Z=Math.min(1,Math.max(0,se*q*(.9+.1*ue)*(.85+.3*le)))}else Z=0;return d+(p-d)*Z}ut(()=>{yt("audio-level",se=>{k=Math.min(1,se.payload*100)}).then(se=>{h=se});let N=0;function F(){N+=.016,y+=(k-y)*.35,k*=.86;const se=e().audio_ready!==!1,j=new Array(u);for(let I=0;I{h&&h(),cancelAnimationFrame(v)}});var D=Jd();let U;var Y=o(D),z=o(Y);let b;var L=r(z,2),G=o(L);{var ae=N=>{var F=Ee("PROCESSING");g(N,F)},oe=N=>{var F=Ee("STANDBY");g(N,F)},de=N=>{var F=Ee("LISTENING");g(N,F)};B(G,N=>{e().processing?N(ae):l()&&!a(C)?N(oe,1):N(de,-1)})}var w=r(Y,2);bt(w,21,()=>a(_),gt,(N,F)=>{var se=Gd();let j;J(()=>{var I;j=ye(se,1,"bar svelte-12wa5lj",null,j,{dim:l()&&!a(C),processing:e().processing}),$s(se,`height: ${(I=a(F))!=null?I:""}px`)}),g(N,se)});var X=r(w,4),V=o(X);J(()=>{U=ye(D,1,"mono svelte-12wa5lj",null,U,{on:c()}),b=ye(z,1,"dot svelte-12wa5lj",null,b,{lit:!e().processing&&!(l()&&!a(C)),processing:e().processing,standby:l()&&!a(C)}),ee(V,a(x))}),g(s,D),Xe(),i()}var Zd=T('
'),Qd=T('
SPECTRUM // EQ-16 OUT ▸
');function ev(s,t){Je(t,!0);const e=()=>St(Ct,"$status",n),[n,i]=_s();let l=Ve(t,"recording",3,!1),c=Ve(t,"active",3,!0);const u=16,d=6,p=96;let _=W(Ue(Array(u).fill(d))),h=null,v,k=0,y=0;const C=he(()=>e().audio_ready!==!1),x=he(()=>e().active_target_label||"Focused Window");function S(F,se,j,I,re,ve,le,E){const q=F/(se-1);let Z;if(ve)Z=Math.pow(Math.sin(I*2.4-q*6)*.5+.5,1.5);else if(re&&!le)Z=E*.06;else if(re){const ue=2+q*9,ie=F*.7,ne=Math.sin(I*ue+ie)*.5+.5,_e=1-q*.35;Z=Math.min(1,Math.max(0,j*_e*(.35+.65*ne)*(.7+.6*E)))}else Z=0;return d+(p-d)*Z}ut(()=>{yt("audio-level",j=>{k=Math.min(1,j.payload*100)}).then(j=>{h=j});let F=0;function se(){F+=.016,y+=(k-y)*.35,k*=.86;const j=e().audio_ready!==!1,I=new Array(u);for(let re=0;re{h&&h(),cancelAnimationFrame(v)}});var D=Qd();let U;var Y=o(D),z=o(Y);let b;var L=r(z,4),G=o(L);{var ae=F=>{var se=Ee("· ANALYZING");g(F,se)},oe=F=>{var se=Ee("· WARMING UP");g(F,se)},de=F=>{var se=Ee("· LIVE");g(F,se)};B(G,F=>{e().processing?F(ae):l()&&!a(C)?F(oe,1):F(de,-1)})}var w=r(L,4),X=r(o(w),2),V=o(X),N=r(Y,4);bt(N,21,()=>a(_),gt,(F,se)=>{var j=Zd();J(()=>{var I;return $s(j,`height: ${(I=a(se))!=null?I:""}px; opacity: ${.45+.55*(a(se)/p)}`)}),g(F,j)}),J(()=>{U=ye(D,1,"spectrum svelte-194vixl",null,U,{on:c()}),b=ye(z,1,"led svelte-194vixl",null,b,{processing:e().processing,standby:l()&&!a(C)}),ee(V,a(x))}),g(s,D),Xe(),i()}var tv=T('
VOXCTRL — /dev/mic0
');function sv(s,t){Je(t,!0);const e=()=>St(Ct,"$status",n),[n,i]=_s();let l=Ve(t,"recording",3,!1),c=Ve(t,"active",3,!0);const u=20;let d=W(Ue("·".repeat(u))),p=W(!1),_=null,h,v=0,k=0;const y=he(()=>e().audio_ready!==!1),C=he(()=>e().active_target_label||"Focused Window");function x(I,re,ve,le,E){const q=u;if(le){const Z=2*q,ue=Math.floor(re*10)%Z,ie=ue_e===ie?"█":"·").join("")}else{if(ve&&!E)return Array.from({length:q},(Z,ue)=>ue%4===0?"·":" ").join("");if(ve){const Z=Math.round(Math.min(1,Math.max(0,I))*q);return Array.from({length:q},(ue,ie)=>ie{yt("audio-level",ve=>{v=Math.min(1,ve.payload*100)}).then(ve=>{_=ve});let I=0;function re(){I+=.016,k+=(v-k)*.35,v*=.86;const ve=e().audio_ready!==!1;f(d,x(k,I,l(),e().processing,ve),!0),f(p,Math.sin(I*5.5)>0),h=requestAnimationFrame(re)}return h=requestAnimationFrame(re),()=>{_&&_(),cancelAnimationFrame(h)}});var S=tv();let D;var U=r(o(S),2),Y=o(U),z=o(Y),b=r(Y,2);let L;var G=o(b);{var ae=I=>{var re=Ee("[PROC]");g(I,re)},oe=I=>{var re=Ee("[INIT]");g(I,re)},de=I=>{var re=Ee("[REC ]");g(I,re)};B(G,I=>{e().processing?I(ae):l()&&!a(y)?I(oe,1):I(de,-1)})}var w=r(G),X=r(b,2),V=o(X);{var N=I=>{var re=Ee("transcribing audio stream");g(I,re)},F=I=>{var re=Ee("connecting input device");g(I,re)},se=I=>{var re=Ee("streaming to output");g(I,re)};B(V,I=>{e().processing?I(N):l()&&!a(y)?I(F,1):I(se,-1)})}var j=r(V,1,!0);J(()=>{var I,re;D=ye(S,1,"terminal svelte-pvtvge",null,D,{on:c()}),ee(z,`$ voxctrl listen --target "${(I=a(C))!=null?I:""}"`),L=ye(b,1,"line2 svelte-pvtvge",null,L,{processing:e().processing,standby:l()&&!a(y)}),ee(w,` ${(re=a(d))!=null?re:""}`),ee(j,a(p)?"_":" ")}),g(s,S),Xe(),i()}var av=T('
VU
-20
0
+3
');function nv(s,t){Je(t,!0);const e=()=>St(Ct,"$status",n),[n,i]=_s();let l=Ve(t,"recording",3,!1),c=Ve(t,"active",3,!0);const u=144,d=70,p=58,_=-.95,h=.95,v=.016;let k=W(Ue(z(_))),y=null,C,x=0,S=0;const D=he(()=>e().audio_ready!==!1),U=he(()=>e().active_target_label||"Focused Window");function Y(le){return _+Math.min(1,Math.max(0,le))*(h-_)}function z(le){const E=u+Math.sin(le)*p,q=d-Math.cos(le)*p;return`M ${u} ${d} L ${E.toFixed(1)} ${q.toFixed(1)}`}function b(le,E,q){const ie=256*(E-le.x)-24.96*le.v;le.v+=ie*q,le.x+=le.v*q,Math.abs(le.x-E)<.001&&Math.abs(le.v)<.02&&(le.x=E,le.v=0)}ut(()=>{yt("audio-level",Z=>{x=Math.min(1,Z.payload*100)}).then(Z=>{y=Z});let le=0;const E={x:_,v:0};function q(){le+=v,S+=(x-S)*.35,x*=.86;const Z=e().audio_ready!==!1;let ue;e().processing?ue=Y(.3+.25*Math.abs(Math.sin(le*2))):l()&&Z?ue=Y(S):ue=_,b(E,ue,v),f(k,z(E.x),!0),C=requestAnimationFrame(q)}return C=requestAnimationFrame(q),()=>{y&&y(),cancelAnimationFrame(C)}});var L=av();let G;var ae=o(L),oe=r(o(ae),2),de=o(oe);{var w=le=>{var E=Ee("ANALOG // PROCESSING");g(le,E)},X=le=>{var E=Ee("ANALOG // WARMING UP");g(le,E)},V=le=>{var E=Ee("ANALOG // INPUT LEVEL");g(le,E)};B(de,le=>{e().processing?le(w):l()&&!a(D)?le(X,1):le(V,-1)})}var N=r(oe,4);let F;var se=r(ae,2),j=r(o(se),20),I=o(j),re=r(se,2),ve=o(re);J(()=>{G=ye(L,1,"vinyl svelte-kq5b5i",null,G,{on:c()}),F=ye(N,1,"led svelte-kq5b5i",null,F,{processing:e().processing,standby:l()&&!a(D)}),mt(I,"d",a(k)),ee(ve,a(U))}),g(s,L),Xe(),i()}var iv=T("
",1),rv=T(''),lv=T('
SYSTEM RESPONDING
'),ov=T('
RECORDING
'),cv=T(" ",1),uv=T('
');function dv(s,t){Je(t,!0);const e=()=>St(Yt,"$config",u),n=()=>St(Ct,"$status",u),i=()=>St(uc,"$recording",u),l=()=>St(dc,"$speaking",u),c=()=>St(vc,"$mcpRecording",u),[u,d]=_s();let p=W(!0),_=W(Ue([])),h=he(()=>a(_).find(w=>w.name===e().ui.overlay_style));const v=he(()=>n().active_target_label||"Focused Window"),k=he(()=>n().active_target_label||"Focused Window");let y=he(()=>i()&&e().ui.show_overlay||l()&&e().tts.enabled&&e().tts.response_overlay||c()&&e().mcp.visual_feedback),C=W(!1),x=W(!1),S,D;ka(()=>(a(y)?(S&&clearTimeout(S),f(C,!0),D&&clearTimeout(D),D=setTimeout(()=>{f(x,!0)},25)):(f(x,!1),S=setTimeout(()=>{f(C,!1)},450)),()=>{S&&clearTimeout(S),D&&clearTimeout(D)}));let U=he(()=>a(h)?a(h).html.replace(/\{\{trigger\}\}/g,a(v)).replace(/\{\{target\}\}/g,a(k)):""),Y=0,z=W(0),b=null,L;ka(()=>{e().ui.overlay_style,f(p,!1);const w=setTimeout(()=>{f(p,!0)},25);return()=>clearTimeout(w)}),ka(()=>{const w=document.documentElement;w.style.setProperty("--voxctrl-audio-level",String(a(z))),w.style.setProperty("--voxctrl-recording",i()?"1":"0"),w.style.setProperty("--voxctrl-processing",n().processing?"1":"0"),w.style.setProperty("--voxctrl-speaking",l()?"1":"0"),w.style.setProperty("--voxctrl-mcp-recording",c()?"1":"0"),w.style.setProperty("--voxctrl-audio-ready",n().audio_ready!==!1?"1":"0")}),ut(()=>{document.documentElement.classList.add("overlay-window"),document.body.classList.add("overlay-window"),document.documentElement.style.setProperty("background","transparent","important"),document.body.style.setProperty("background","transparent","important");const w=document.getElementById("app");w&&w.style.setProperty("background","transparent","important"),M("get_custom_overlays").then(V=>{f(_,V,!0)}).catch(V=>{console.error("Failed to load custom overlays:",V)}),yt("audio-level",V=>{Y=Math.min(1,V.payload*100),window.dispatchEvent(new CustomEvent("voxctrl-audio-level",{detail:V.payload}))}).then(V=>{b=V});function X(){f(z,a(z)+(Y-a(z))*.42),Y*=.82,a(h)&&window.dispatchEvent(new CustomEvent("voxctrl-status",{detail:{recording:i(),processing:n().processing,speaking:l(),audio_ready:n().audio_ready!==!1,active_target_label:n().active_target_label||"Focused Window",audio_level:a(z)}})),L=requestAnimationFrame(X)}return L=requestAnimationFrame(X),()=>{document.documentElement.classList.remove("overlay-window"),document.body.classList.remove("overlay-window"),b&&b(),cancelAnimationFrame(L)}});function G(w){return w.querySelectorAll("script").forEach(V=>{const N=document.createElement("script");Array.from(V.attributes).forEach(F=>{N.setAttribute(F.name,F.value)}),N.appendChild(document.createTextNode(V.innerHTML)),V.parentNode&&V.parentNode.replaceChild(N,V)}),{destroy(){window.dispatchEvent(new CustomEvent("voxctrl-cleanup"))}}}var ae=uv(),oe=o(ae);{var de=w=>{var X=cv(),V=Ot(X);{var N=ie=>{Ud(ie,{get recording(){return i()},get active(){return a(x)}})},F=ie=>{Hd(ie,{get recording(){return i()},get active(){return a(x)}})},se=ie=>{Yd(ie,{get recording(){return i()},get speaking(){return l()},get active(){return a(x)}})},j=ie=>{Xd(ie,{get recording(){return i()},get active(){return a(x)}})},I=ie=>{ev(ie,{get recording(){return i()},get active(){return a(x)}})},re=ie=>{sv(ie,{get recording(){return i()},get active(){return a(x)}})},ve=ie=>{nv(ie,{get recording(){return i()},get active(){return a(x)}})},le=ie=>{var ne=iv(),_e=Ot(ne);Ki(_e,()=>``);var Ie=r(_e,2);let P;Ki(Ie,()=>a(U),!0),ua(Ie,K=>G==null?void 0:G(K)),J(()=>P=ye(Ie,1,"custom-overlay-content svelte-rmqsd6",null,P,{active:a(x)})),g(ie,ne)},E=ie=>{qd(ie,{get recording(){return i()},get speaking(){return l()},get active(){return a(x)}})};B(V,ie=>{e().ui.overlay_style==="waveform"?ie(N):e().ui.overlay_style==="pulse"?ie(F,1):e().ui.overlay_style==="blue_wave"?ie(se,2):e().ui.overlay_style==="mono_bars"?ie(j,3):e().ui.overlay_style==="spectrum"?ie(I,4):e().ui.overlay_style==="terminal"?ie(re,5):e().ui.overlay_style==="vinyl"?ie(ve,6):a(h)?ie(le,7):e().ui.overlay_style!=="none"&&ie(E,8)})}var q=r(V,2);{var Z=ie=>{var ne=lv();let _e;var Ie=o(ne);bt(Ie,20,()=>[0,1,2,3,4],gt,(ce,O)=>{var A=rv();J(()=>$s(A,`animation-delay: ${O*.13}s`)),g(ce,A)});var P=r(Ie,2),K=r(o(P),2),$=o(K);J(()=>{var ce;_e=ye(ne,1,"system-response-box speaking svelte-rmqsd6",null,_e,{on:a(x)}),ee($,`▸ ${(ce=a(k))!=null?ce:""}`)}),g(ie,ne)},ue=ie=>{var ne=ov();let _e;var Ie=r(o(ne),2),P=r(o(Ie),2),K=o(P);J(()=>{var $;_e=ye(ne,1,"system-response-box mcp svelte-rmqsd6",null,_e,{on:a(x)}),ee(K,`▸ ${($=a(k))!=null?$:""}`)}),g(ie,ne)};B(q,ie=>{l()?ie(Z):c()&&ie(ue,1)})}g(w,X)};B(oe,w=>{a(C)&&a(p)&&w(de)})}J(()=>{mt(ae,"data-recording",i()),mt(ae,"data-speaking",l()),mt(ae,"data-processing",n().processing)}),g(s,ae),Xe(),d()}var vv=T('
🚫

History Disabled

Transcript history is turned off. Enable it in Settings → General to start logging.

'),pv=T('
Retrieving transcript log...
'),fv=T('
📭

Log is Empty

Your transcribed speech sessions will appear here.

'),hv=T('

'),_v=T('
'),gv=T('

Transcript History

DICTATION LOGS FOR THIS SESSION

');function bv(s,t){Je(t,!0);const e=()=>St(Yt,"$config",n),[n,i]=_s();let l=W(Ue([])),c=W(Ue([])),u=W(!0),d=he(()=>new Map(a(c).map(b=>[b.id,b])));async function p(){try{const b=await M("get_history");f(l,b.slice(0,100),!0)}catch(b){console.error("Failed to load history",b)}}ut(()=>{(async()=>{try{const[G,ae]=await Promise.all([M("get_history"),M("get_targets")]);f(l,G.slice(0,100),!0),f(c,ae,!0)}catch(G){console.error("Failed to load history or targets",G)}finally{f(u,!1)}})();let b,L;return yt("tauri://focus",()=>p()).then(G=>b=G),yt("status-tick",()=>p()).then(G=>L=G),()=>{b==null||b(),L==null||L()}});async function _(){await M("clear_history"),f(l,[],!0)}function h(b){try{const L=new Date(b);return isNaN(L.getTime())?"Unknown Time":L.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return"Unknown Time"}}function v(b){var G;return(G={inject:"Inject",clipboard:"Clipboard",exec:"Exec",pipe:"Pipe",socket:"Socket",file:"File",dbus:"DBus",http:"HTTP",webhook:"Webhook",mcp:"MCP"}[b])!=null?G:b}function k(b){return b?b.split(",").map(G=>G.trim()).filter(G=>G.length>0).map(G=>{const ae=a(d).get(G);return ae?`${ae.label} (${v(ae.delivery)})`:G==="default"?"Focused Window (Inject)":G}).join(" + "):""}var y=gv(),C=o(y),x=r(o(C),2),S=r(C,2);{var D=b=>{var L=vv();g(b,L)},U=b=>{var L=pv();g(b,L)},Y=b=>{var L=fv();g(b,L)},z=b=>{var L=_v();bt(L,21,()=>a(l),gt,(G,ae)=>{var oe=hv(),de=o(oe),w=r(o(de),2),X=o(w),V=r(w,2),N=r(de,2),F=o(N),se=o(F),j=r(o(se)),I=r(se,2),re=r(o(I)),ve=r(F,2),le=r(o(ve));J((E,q)=>{var Z;ee(X,a(ae).text),ee(j,` ${E!=null?E:""}`),ee(re,` ${(Z=a(ae).inference_ms)!=null?Z:""}ms`),ee(le,` ${q!=null?q:""}`)},[()=>h(a(ae).timestamp),()=>k(a(ae).target_id)]),H("click",V,()=>navigator.clipboard.writeText(a(ae).text)),g(G,oe)}),g(b,L)};B(S,b=>{var L,G;(G=(L=e())==null?void 0:L.ui)!=null&&G.history_enabled?a(u)?b(U,1):a(l).length===0?b(Y,2):b(z,-1):b(D)})}H("click",x,_),g(s,y),Xe(),i()}Vt(["click"]);class Oi{constructor(...t){this.type="Logical",t.length===1?"Logical"in t[0]?(this.width=t[0].Logical.width,this.height=t[0].Logical.height):(this.width=t[0].width,this.height=t[0].height):(this.width=t[0],this.height=t[1])}toPhysical(t){return new Hs(this.width*t,this.height*t)}[os](){return{width:this.width,height:this.height}}toJSON(){return this[os]()}}class Hs{constructor(...t){this.type="Physical",t.length===1?"Physical"in t[0]?(this.width=t[0].Physical.width,this.height=t[0].Physical.height):(this.width=t[0].width,this.height=t[0].height):(this.width=t[0],this.height=t[1])}toLogical(t){return new Oi(this.width/t,this.height/t)}[os](){return{width:this.width,height:this.height}}toJSON(){return this[os]()}}class ba{constructor(t){this.size=t}toLogical(t){return this.size instanceof Oi?this.size:this.size.toLogical(t)}toPhysical(t){return this.size instanceof Hs?this.size:this.size.toPhysical(t)}[os](){return{[`${this.size.type}`]:{width:this.size.width,height:this.size.height}}}toJSON(){return this[os]()}}class Di{constructor(...t){this.type="Logical",t.length===1?"Logical"in t[0]?(this.x=t[0].Logical.x,this.y=t[0].Logical.y):(this.x=t[0].x,this.y=t[0].y):(this.x=t[0],this.y=t[1])}toPhysical(t){return new as(this.x*t,this.y*t)}[os](){return{x:this.x,y:this.y}}toJSON(){return this[os]()}}class as{constructor(...t){this.type="Physical",t.length===1?"Physical"in t[0]?(this.x=t[0].Physical.x,this.y=t[0].Physical.y):(this.x=t[0].x,this.y=t[0].y):(this.x=t[0],this.y=t[1])}toLogical(t){return new Di(this.x/t,this.y/t)}[os](){return{x:this.x,y:this.y}}toJSON(){return this[os]()}}class bn{constructor(t){this.position=t}toLogical(t){return this.position instanceof Di?this.position:this.position.toLogical(t)}toPhysical(t){return this.position instanceof as?this.position:this.position.toPhysical(t)}[os](){return{[`${this.position.type}`]:{x:this.position.x,y:this.position.y}}}toJSON(){return this[os]()}}var In;(function(s){s[s.Critical=1]="Critical",s[s.Informational=2]="Informational"})(In||(In={}));class rl{constructor(t){this._preventDefault=!1,this.event=t.event,this.id=t.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}var hi;(function(s){s.None="none",s.Normal="normal",s.Indeterminate="indeterminate",s.Paused="paused",s.Error="error"})(hi||(hi={}));function Ii(){return new Li(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}async function An(){return M("plugin:window|get_all_windows").then(s=>s.map(t=>new Li(t,{skip:!0})))}const Xn=["tauri://created","tauri://error"];class Li{constructor(t,e={}){var n;this.label=t,this.listeners=Object.create(null),e!=null&&e.skip||M("plugin:window|create",{options:{...e,parent:typeof e.parent=="string"?e.parent:(n=e.parent)===null||n===void 0?void 0:n.label,label:t}}).then(async()=>this.emit("tauri://created")).catch(async i=>this.emit("tauri://error",i))}static async getByLabel(t){var e;return(e=(await An()).find(n=>n.label===t))!==null&&e!==void 0?e:null}static getCurrent(){return Ii()}static async getAll(){return An()}static async getFocusedWindow(){for(const t of await An())if(await t.isFocused())return t;return null}async listen(t,e){return this._handleTauriEvent(t,e)?()=>{const n=this.listeners[t];n.splice(n.indexOf(e),1)}:yt(t,e,{target:{kind:"Window",label:this.label}})}async once(t,e){return this._handleTauriEvent(t,e)?()=>{const n=this.listeners[t];n.splice(n.indexOf(e),1)}:ic(t,e,{target:{kind:"Window",label:this.label}})}async emit(t,e){if(Xn.includes(t)){for(const n of this.listeners[t]||[])n({event:t,id:-1,payload:e});return}return rc(t,e)}async emitTo(t,e,n){if(Xn.includes(e)){for(const i of this.listeners[e]||[])i({event:e,id:-1,payload:n});return}return lc(t,e,n)}_handleTauriEvent(t,e){return Xn.includes(t)?(t in this.listeners?this.listeners[t].push(e):this.listeners[t]=[e],!0):!1}async scaleFactor(){return M("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return M("plugin:window|inner_position",{label:this.label}).then(t=>new as(t))}async outerPosition(){return M("plugin:window|outer_position",{label:this.label}).then(t=>new as(t))}async innerSize(){return M("plugin:window|inner_size",{label:this.label}).then(t=>new Hs(t))}async outerSize(){return M("plugin:window|outer_size",{label:this.label}).then(t=>new Hs(t))}async isFullscreen(){return M("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return M("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return M("plugin:window|is_maximized",{label:this.label})}async isFocused(){return M("plugin:window|is_focused",{label:this.label})}async isDecorated(){return M("plugin:window|is_decorated",{label:this.label})}async isResizable(){return M("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return M("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return M("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return M("plugin:window|is_closable",{label:this.label})}async isVisible(){return M("plugin:window|is_visible",{label:this.label})}async title(){return M("plugin:window|title",{label:this.label})}async theme(){return M("plugin:window|theme",{label:this.label})}async isAlwaysOnTop(){return M("plugin:window|is_always_on_top",{label:this.label})}async activityName(){return M("plugin:window|activity_name",{label:this.label})}async sceneIdentifier(){return M("plugin:window|scene_identifier",{label:this.label})}async center(){return M("plugin:window|center",{label:this.label})}async requestUserAttention(t){let e=null;return t&&(t===In.Critical?e={type:"Critical"}:e={type:"Informational"}),M("plugin:window|request_user_attention",{label:this.label,value:e})}async setResizable(t){return M("plugin:window|set_resizable",{label:this.label,value:t})}async setEnabled(t){return M("plugin:window|set_enabled",{label:this.label,value:t})}async isEnabled(){return M("plugin:window|is_enabled",{label:this.label})}async setMaximizable(t){return M("plugin:window|set_maximizable",{label:this.label,value:t})}async setMinimizable(t){return M("plugin:window|set_minimizable",{label:this.label,value:t})}async setClosable(t){return M("plugin:window|set_closable",{label:this.label,value:t})}async setTitle(t){return M("plugin:window|set_title",{label:this.label,value:t})}async maximize(){return M("plugin:window|maximize",{label:this.label})}async unmaximize(){return M("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return M("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return M("plugin:window|minimize",{label:this.label})}async unminimize(){return M("plugin:window|unminimize",{label:this.label})}async show(){return M("plugin:window|show",{label:this.label})}async hide(){return M("plugin:window|hide",{label:this.label})}async close(){return M("plugin:window|close",{label:this.label})}async destroy(){return M("plugin:window|destroy",{label:this.label})}async setDecorations(t){return M("plugin:window|set_decorations",{label:this.label,value:t})}async setShadow(t){return M("plugin:window|set_shadow",{label:this.label,value:t})}async setEffects(t){return M("plugin:window|set_effects",{label:this.label,value:t})}async clearEffects(){return M("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(t){return M("plugin:window|set_always_on_top",{label:this.label,value:t})}async setAlwaysOnBottom(t){return M("plugin:window|set_always_on_bottom",{label:this.label,value:t})}async setContentProtected(t){return M("plugin:window|set_content_protected",{label:this.label,value:t})}async setSize(t){return M("plugin:window|set_size",{label:this.label,value:t instanceof ba?t:new ba(t)})}async setMinSize(t){return M("plugin:window|set_min_size",{label:this.label,value:t instanceof ba?t:t?new ba(t):null})}async setMaxSize(t){return M("plugin:window|set_max_size",{label:this.label,value:t instanceof ba?t:t?new ba(t):null})}async setSizeConstraints(t){function e(n){return n?{Logical:n}:null}return M("plugin:window|set_size_constraints",{label:this.label,value:{minWidth:e(t==null?void 0:t.minWidth),minHeight:e(t==null?void 0:t.minHeight),maxWidth:e(t==null?void 0:t.maxWidth),maxHeight:e(t==null?void 0:t.maxHeight)}})}async setPosition(t){return M("plugin:window|set_position",{label:this.label,value:t instanceof bn?t:new bn(t)})}async setFullscreen(t){return M("plugin:window|set_fullscreen",{label:this.label,value:t})}async setSimpleFullscreen(t){return M("plugin:window|set_simple_fullscreen",{label:this.label,value:t})}async setFocus(){return M("plugin:window|set_focus",{label:this.label})}async setFocusable(t){return M("plugin:window|set_focusable",{label:this.label,value:t})}async setIcon(t){return M("plugin:window|set_icon",{label:this.label,value:Dn(t)})}async setSkipTaskbar(t){return M("plugin:window|set_skip_taskbar",{label:this.label,value:t})}async setCursorGrab(t){return M("plugin:window|set_cursor_grab",{label:this.label,value:t})}async setCursorVisible(t){return M("plugin:window|set_cursor_visible",{label:this.label,value:t})}async setCursorIcon(t){return M("plugin:window|set_cursor_icon",{label:this.label,value:t})}async setBackgroundColor(t){return M("plugin:window|set_background_color",{color:t})}async setCursorPosition(t){return M("plugin:window|set_cursor_position",{label:this.label,value:t instanceof bn?t:new bn(t)})}async setIgnoreCursorEvents(t){return M("plugin:window|set_ignore_cursor_events",{label:this.label,value:t})}async startDragging(){return M("plugin:window|start_dragging",{label:this.label})}async startResizeDragging(t){return M("plugin:window|start_resize_dragging",{label:this.label,value:t})}async setBadgeCount(t){return M("plugin:window|set_badge_count",{label:this.label,value:t})}async setBadgeLabel(t){return M("plugin:window|set_badge_label",{label:this.label,value:t})}async setOverlayIcon(t){return M("plugin:window|set_overlay_icon",{label:this.label,value:t?Dn(t):void 0})}async setProgressBar(t){return M("plugin:window|set_progress_bar",{label:this.label,value:t})}async setVisibleOnAllWorkspaces(t){return M("plugin:window|set_visible_on_all_workspaces",{label:this.label,value:t})}async setTitleBarStyle(t){return M("plugin:window|set_title_bar_style",{label:this.label,value:t})}async setTheme(t){return M("plugin:window|set_theme",{label:this.label,value:t})}async onResized(t){return this.listen(jt.WINDOW_RESIZED,e=>{e.payload=new Hs(e.payload),t(e)})}async onMoved(t){return this.listen(jt.WINDOW_MOVED,e=>{e.payload=new as(e.payload),t(e)})}async onCloseRequested(t){return this.listen(jt.WINDOW_CLOSE_REQUESTED,async e=>{const n=new rl(e);await t(n),n.isPreventDefault()||await this.destroy()})}async onDragDropEvent(t){const e=await this.listen(jt.DRAG_ENTER,c=>{t({...c,payload:{type:"enter",paths:c.payload.paths,position:new as(c.payload.position)}})}),n=await this.listen(jt.DRAG_OVER,c=>{t({...c,payload:{type:"over",position:new as(c.payload.position)}})}),i=await this.listen(jt.DRAG_DROP,c=>{t({...c,payload:{type:"drop",paths:c.payload.paths,position:new as(c.payload.position)}})}),l=await this.listen(jt.DRAG_LEAVE,c=>{t({...c,payload:{type:"leave"}})});return()=>{e(),i(),n(),l()}}async onFocusChanged(t){const e=await this.listen(jt.WINDOW_FOCUS,i=>{t({...i,payload:!0})}),n=await this.listen(jt.WINDOW_BLUR,i=>{t({...i,payload:!1})});return()=>{e(),n()}}async onScaleChanged(t){return this.listen(jt.WINDOW_SCALE_FACTOR_CHANGED,t)}async onThemeChanged(t){return this.listen(jt.WINDOW_THEME_CHANGED,t)}}var Xi;(function(s){s.Disabled="disabled",s.Throttle="throttle",s.Suspend="suspend"})(Xi||(Xi={}));var Zi;(function(s){s.Default="default",s.FluentOverlay="fluentOverlay"})(Zi||(Zi={}));var _i;(function(s){s.AppearanceBased="appearanceBased",s.Light="light",s.Dark="dark",s.MediumLight="mediumLight",s.UltraDark="ultraDark",s.Titlebar="titlebar",s.Selection="selection",s.Menu="menu",s.Popover="popover",s.Sidebar="sidebar",s.HeaderView="headerView",s.Sheet="sheet",s.WindowBackground="windowBackground",s.HudWindow="hudWindow",s.FullScreenUI="fullScreenUI",s.Tooltip="tooltip",s.ContentBackground="contentBackground",s.UnderWindowBackground="underWindowBackground",s.UnderPageBackground="underPageBackground",s.Mica="mica",s.Blur="blur",s.Acrylic="acrylic",s.Tabbed="tabbed",s.TabbedDark="tabbedDark",s.TabbedLight="tabbedLight"})(_i||(_i={}));var gi;(function(s){s.FollowsWindowActiveState="followsWindowActiveState",s.Active="active",s.Inactive="inactive"})(gi||(gi={}));function Bn(s){return s===null?null:{name:s.name,scaleFactor:s.scaleFactor,position:new as(s.position),size:new Hs(s.size),workArea:{position:new as(s.workArea.position),size:new Hs(s.workArea.size)}}}async function mv(){return M("plugin:window|current_monitor").then(Bn)}async function yv(){return M("plugin:window|primary_monitor").then(Bn)}async function wv(s,t){return M("plugin:window|monitor_from_point",{x:s,y:t}).then(Bn)}async function xv(){return M("plugin:window|available_monitors").then(s=>s.map(Bn))}async function kv(){return M("plugin:window|cursor_position").then(s=>new as(s))}const Tv=Object.freeze(Object.defineProperty({__proto__:null,CloseRequestedEvent:rl,get Effect(){return _i},get EffectState(){return gi},LogicalPosition:Di,LogicalSize:Oi,PhysicalPosition:as,PhysicalSize:Hs,get ProgressBarStatus(){return hi},get UserAttentionType(){return In},Window:Li,availableMonitors:xv,currentMonitor:mv,cursorPosition:kv,getAllWindows:An,getCurrentWindow:Ii,monitorFromPoint:wv,primaryMonitor:yv},Symbol.toStringTag,{value:"Module"}));var Ev=T('
Configuring system dependencies & hotkey rules...

You may be prompted to enter your root/administrator password.

'),Sv=T('Hardware hotkey rules are configured, but your active session is missing input group permissions. Please log out and log back in (or reboot) for these settings to take effect. This screen will keep appearing at startup until hotkey permissions are working.',1),Av=T('
'),Cv=T(''),Pv=T(''),Mv=T('
Verifying hardware permissions...
'),Ov=T('
');function Dv(s,t){Je(t,!0);let e=W(null),n=W(!1),i=W(null);ut(async()=>{try{const v=await M("check_udev_status");f(e,v,!0)}catch(v){console.error("Failed to check udev status in diagnostics window:",v)}});async function l(){try{await Ii().close()}catch(v){console.error("Failed to close window natively:",v)}}async function c(){f(n,!0),f(i,null);try{const v=await M("install_system_integration");f(e,v,!0)}catch(v){console.error("Failed to install system integration:",v),f(i,v.toString(),!0)}finally{f(n,!1)}}var u=Ov(),d=o(u);{var p=v=>{var k=Ev();g(v,k)},_=v=>{var k=Pv(),y=o(k),C=o(y),x=r(y,2),S=o(x),D=r(x,2),U=o(D);{var Y=V=>{var N=Ee("Hardware hotkey permissions are configured and working in this session. You're all set — global keyboard shortcuts are active.");g(V,N)},z=V=>{var N=Sv();g(V,N)},b=V=>{var N=Ee("VoxCtrl requires global hotkey setup to capture keyboard shortcuts natively. Click below to automatically configure udev rules, input group membership, and desktop integration launcher files. This screen will keep appearing at startup until hotkey permissions are working.");g(V,N)};B(U,V=>{a(e).is_configured?V(Y):a(e).needs_relogin?V(z,1):V(b,-1)})}var L=r(D,2);{var G=V=>{var N=Av(),F=r(o(N),2),se=o(F);J(()=>ee(se,a(i))),g(V,N)};B(L,V=>{a(i)&&V(G)})}var ae=r(L,2),oe=o(ae);{var de=V=>{var N=Cv();H("click",N,c),g(V,N)};B(oe,V=>{!a(e).is_configured&&!a(e).needs_relogin&&V(de)})}var w=r(oe,2),X=o(w);J(()=>{ee(C,a(e).is_configured?"✅":a(e).needs_relogin?"🔄":"⚠️"),ee(S,a(e).is_configured?"Permissions Configured":a(e).needs_relogin?"Relogin Required":"Hardware Permissions Required"),ee(X,a(e).is_configured||a(e).needs_relogin?"Close":"Continue Anyway")}),H("click",w,l),g(v,k)},h=v=>{var k=Mv();g(v,k)};B(d,v=>{a(n)?v(p):a(e)?v(_,1):v(h,-1)})}g(s,u),Xe()}Vt(["click"]);function Iv(s){const t=window.location.pathname;function e(){return t.startsWith("/overlay")?"overlay":t.startsWith("/history")?"history":t.startsWith("/udev-warning")?"udev-warning":"settings"}const n=e();n==="overlay"&&(document.documentElement.classList.add("overlay-window"),document.body.classList.add("overlay-window"));var i=Zr(),l=Ot(i);{var c=_=>{dv(_,{})},u=_=>{bv(_,{})},d=_=>{Dv(_,{})},p=_=>{Rd(_,{})};B(l,_=>{n==="overlay"?_(c):n==="history"?_(u,1):n==="udev-warning"?_(d,2):_(p,-1)})}g(s,i)}No(Iv,{target:document.getElementById("app")}); diff --git a/dist/index.html b/dist/index.html index 187cdd4..564f932 100644 --- a/dist/index.html +++ b/dist/index.html @@ -16,7 +16,7 @@ - + diff --git a/docs/configuration.md b/docs/configuration.md index 2e240c8..05c3f92 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -127,7 +127,20 @@ The `.en` variants are English-only but slightly faster. `large-v3-turbo` is a d | Key | Type | Default | Description | |---|---|---|---| | `model_size` | string | `"base"` | `"base"` or `"tiny"` | -| `language` | string | `"en"` | BCP-47 language code | +| `language` | string | `"en"` | BCP-47 language code (output label only) | + +> **Build requirement:** the Moonshine backend is an opt-in compile-time +> feature. It is included only when the app is built with `--features moonshine` +> (it pulls in ONNX Runtime). In a build **without** that feature, selecting +> `"moonshine"` transparently falls back to `whisper-cpp` and still uses the +> Whisper model configured above. The Settings → Engine panel shows whether +> Moonshine is available in the running build. +> +> Moonshine models are the four upstream ONNX graphs +> (`preprocess`, `encode`, `uncached_decode`, `cached_decode`) plus a +> `tokenizer.json`, downloaded on demand into +> `~/.local/share/voxctrl/models/moonshine//`. You can also place those +> files there manually to run fully offline. ### `audio` section diff --git a/docs/speech-recognition.md b/docs/speech-recognition.md index 2159ab4..673fae4 100644 --- a/docs/speech-recognition.md +++ b/docs/speech-recognition.md @@ -219,3 +219,28 @@ Under `engine.whisper_cpp` in `config.json`: | `model_dir` | string | `""` | Custom model storage path; empty = `~/.local/share/voxctrl/models/`. Supports `~` expansion (e.g. `~/.whisper-models`). The directory must already exist. | Language detection is automatic when using whisper-cpp; use the `engine.moonshine.language` field for the Moonshine backend. + +## Moonshine backend + +[Moonshine](https://github.com/moonshine-ai/moonshine) is an alternative, +CPU-friendly speech-to-text model. Unlike Whisper it consumes the raw 16 kHz +waveform directly (no fixed 30-second window), which keeps latency low on the +short utterances typical of push-to-talk dictation. + +It runs through ONNX Runtime as four graphs executed in sequence — +`preprocess` → `encode` → `uncached_decode` → `cached_decode` — with greedy +autoregressive decoding: starting from the start-of-transcript token, each +step's highest-scoring token is fed back in until the end-of-transcript token +appears (or a length cap derived from the audio duration is reached). The +resulting token ids are turned back into text with the model's `tokenizer.json`. + +**Enabling it.** Moonshine is an opt-in build feature (it links ONNX Runtime), +compiled in with `--features moonshine`, the same way `cuda` and `vulkan` are +opt-in. A build without it will transparently fall back to whisper-cpp if +`"moonshine"` is selected; the Settings → Engine panel indicates whether the +running build actually includes it. + +**Models.** Selecting a size (`base` or `tiny`) and clicking Download in +Settings → Engine fetches the four ONNX graphs plus `tokenizer.json` into +`~/.local/share/voxctrl/models/moonshine//`. You can also drop those +files there manually to run fully offline. diff --git a/package-lock.json b/package-lock.json index 69ec617..7ac1934 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "voxctrl", - "version": "0.2.6", + "version": "0.2.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "voxctrl", - "version": "0.2.6", + "version": "0.2.8", "dependencies": { "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "^2", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8cf917b..81ee0ee 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -65,6 +65,10 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] cuda = ["voxctrl-inference/cuda"] vulkan = ["voxctrl-inference/vulkan"] +# Compiles the Moonshine ONNX speech-to-text backend into the app. Opt-in like +# cuda/vulkan: it pulls in ONNX Runtime (fetched at build time). Without it, a +# "moonshine" backend selection transparently falls back to whisper-cpp. +moonshine = ["voxctrl-inference/moonshine"] [dev-dependencies] tempfile = { workspace = true } diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index d524ae1..56c7c2c 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -371,6 +371,42 @@ pub async fn download_model(model_size: String, model_dir: String) -> Result<(), .map_err(|e| e.to_string()) } +/// Whether the Moonshine ONNX backend was compiled into this build. The UI uses +/// this to decide whether selecting Moonshine actually runs Moonshine (vs. +/// transparently falling back to whisper-cpp). +#[tauri::command] +pub fn moonshine_available() -> bool { + voxctrl_inference::MOONSHINE_COMPILED +} + +#[tauri::command] +pub async fn check_moonshine_downloaded(model_size: String) -> Result { + #[cfg(feature = "moonshine")] + { + Ok(voxctrl_inference::moonshine::is_model_downloaded(&model_size, "")) + } + #[cfg(not(feature = "moonshine"))] + { + let _ = model_size; + Ok(false) + } +} + +#[tauri::command] +pub async fn download_moonshine_model(model_size: String) -> Result<(), String> { + #[cfg(feature = "moonshine")] + { + voxctrl_inference::moonshine::download_model(&model_size, "") + .await + .map_err(|e| e.to_string()) + } + #[cfg(not(feature = "moonshine"))] + { + let _ = model_size; + Err("This build was compiled without the Moonshine backend. Rebuild with `--features moonshine` to use it.".into()) + } +} + #[tauri::command] pub async fn check_directory_exists(path: String) -> Result { if path.is_empty() { diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 3d2917f..1064df9 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -351,7 +351,12 @@ pub fn run() { { let cfg = state_for_gesture.config.lock().await; let eng = &cfg.data.engine; - if eng.backend != voxctrl_config::BackendChoice::Moonshine + // Moonshine only bypasses the Whisper-model check when it + // is actually compiled in; otherwise the app silently + // falls back to whisper-cpp and still needs the model. + let uses_whisper_model = eng.backend != voxctrl_config::BackendChoice::Moonshine + || !voxctrl_inference::MOONSHINE_COMPILED; + if uses_whisper_model && !voxctrl_inference::whisper_cpp::is_small_auto_downloadable(&eng.whisper_cpp.model_size) && !voxctrl_inference::whisper_cpp::is_model_downloaded( &eng.whisper_cpp.model_size, @@ -765,7 +770,12 @@ pub fn run() { // the background (the shipped default, "tiny"), in which case the // app works out of the box with no Settings visit required. let mut show_settings = cfg_data.ui.auto_show_settings; - if cfg_data.engine.backend != voxctrl_config::BackendChoice::Moonshine { + // Only the whisper-cpp path needs a GGUF model on disk. A Moonshine + // selection uses whisper-cpp (and thus its model) unless the + // Moonshine backend is actually compiled into this build. + let uses_whisper_model = cfg_data.engine.backend != voxctrl_config::BackendChoice::Moonshine + || !voxctrl_inference::MOONSHINE_COMPILED; + if uses_whisper_model { let model_size = cfg_data.engine.whisper_cpp.model_size.clone(); let model_dir = cfg_data.engine.whisper_cpp.model_dir.clone(); if !voxctrl_inference::whisper_cpp::is_model_downloaded(&model_size, &model_dir) { @@ -986,6 +996,9 @@ pub fn run() { list_pocket_tts_voices, check_model_downloaded, download_model, + moonshine_available, + check_moonshine_downloaded, + download_moonshine_model, check_directory_exists, test_openai, cuda_enabled, diff --git a/src/lib/Settings/EngineTab.svelte b/src/lib/Settings/EngineTab.svelte index 345ba78..28c2916 100644 --- a/src/lib/Settings/EngineTab.svelte +++ b/src/lib/Settings/EngineTab.svelte @@ -62,6 +62,52 @@ let downloading = $state(false); let modelDirError = $state(null); + // ── Moonshine ──────────────────────────────────────────────────────────── + // Whether the app was built with the Moonshine backend. When false, choosing + // Moonshine silently runs whisper-cpp, so we surface that to the user. + let moonshineAvailable = $state(true); + let moonshineDownloadedMap = $state>({}); + let moonshineChecking = $state(false); + let moonshineDownloading = $state(false); + + async function checkMoonshineDownloaded() { + moonshineChecking = true; + const newMap: Record = {}; + for (const m of moonshineModelSizeOptions) { + try { + newMap[m.value] = await invoke("check_moonshine_downloaded", { + modelSize: m.value, + }); + } catch (e) { + console.error("Failed to check Moonshine download status for " + m.value, e); + newMap[m.value] = false; + } + } + moonshineDownloadedMap = newMap; + moonshineChecking = false; + } + + async function triggerMoonshineDownload(model: string) { + if (moonshineDownloading) return; + moonshineDownloading = true; + try { + await invoke("download_moonshine_model", { modelSize: model }); + moonshineDownloadedMap[model] = true; + } catch (e) { + alert(`Failed to download Moonshine model: ${e}`); + } finally { + moonshineDownloading = false; + } + } + + async function onMoonshineModelChanged() { + markDirty(); + const selected = cfg.engine.moonshine.model_size; + if (moonshineAvailable && !moonshineDownloadedMap[selected]) { + await triggerMoonshineDownload(selected); + } + } + async function checkAllModelsDownloaded() { checking = true; const newMap: Record = {}; @@ -131,6 +177,12 @@ onMount(async () => { checkAllModelsDownloaded(); + try { + moonshineAvailable = await invoke("moonshine_available"); + } catch (e) { + console.error("Failed to query Moonshine availability", e); + } + checkMoonshineDownloaded(); cudaEnabled = await invoke("cuda_enabled"); // If this is a CPU build but config still says "cuda", reset to "auto" if (!cudaEnabled && cfg.engine.whisper_cpp.device === "cuda") { @@ -242,10 +294,54 @@ {:else}

Moonshine Settings

+ + {#if !moonshineAvailable} +
+ ⚠️ +
+ Moonshine backend not included in this build +

+ This build was compiled without Moonshine, so selecting it will fall + back to Whisper.cpp (using the Whisper model configured above). + Rebuild with --features moonshine to enable it. +

+
+
+ {/if} + + + {#if moonshineAvailable} +
+ {#if moonshineChecking} + ⏳ Checking local model files... + {:else if moonshineDownloading} + ⏳ Downloading Moonshine {cfg.engine.moonshine.model_size} (ONNX)... + {:else if moonshineDownloadedMap[cfg.engine.moonshine.model_size]} + ✔ Model downloaded + {:else} +
+ Model not downloaded + +
+ {/if} +
+ {/if} +