diff --git a/crates/jarvis-app/src/app.rs b/crates/jarvis-app/src/app.rs index 8cc0ed7..bd482af 100644 --- a/crates/jarvis-app/src/app.rs +++ b/crates/jarvis-app/src/app.rs @@ -25,7 +25,7 @@ fn main_loop(text_cmd_rx: Receiver) -> Result<(), ()> { // ring buffer: keeps last 2 seconds of audio (pre-roll) let mut audio_buffer = AudioRingBuffer::new(2.0, frame_length, sample_rate); - + // VAD state let mut vad_state = VadState::WaitingForVoice; let mut silence_frames: u32 = 0; @@ -37,7 +37,8 @@ fn main_loop(text_cmd_rx: Receiver) -> Result<(), ()> { voices::play_greet(); match recorder::start_recording() { - Ok(_) => info!("Recording started."), + Ok(_) => info!("Recording started. Microphone: {}", + recorder::get_audio_device_name(recorder::get_selected_microphone_index())), Err(_) => { error!("Cannot start recording."); return Err(()); @@ -82,6 +83,9 @@ fn main_loop(text_cmd_rx: Receiver) -> Result<(), ()> { } VadState::VoiceActive => { + // dual-feed: speech recognizer gets frames in parallel with wake word detector + let _ = stt::recognize(&frame_buffer, false); + // feed to wake word detector if let Some(_keyword_index) = listener::data_callback(&frame_buffer) { // WAKE WORD DETECTED! @@ -89,20 +93,25 @@ fn main_loop(text_cmd_rx: Receiver) -> Result<(), ()> { ipc::send(IpcEvent::WakeWordDetected); stt::reset_wake_recognizer(); - stt::reset_speech_recognizer(); audio_processing::reset(); - - voices::play_reply(); + + // brief sniff to keep feeding STT while transitioning + let sniff_frames = ((0.3 * sample_rate as f32) / frame_length as f32) as u32; + for _ in 0..sniff_frames { + recorder::read_microphone(&mut frame_buffer); + audio_processing::process(&frame_buffer); + stt::recognize(&frame_buffer, false); + } + ipc::send(IpcEvent::Listening); - - // enter voice recognition mode - recognize_command(&mut frame_buffer, &rt, frame_length, sample_rate); - + recognize_command(&mut frame_buffer, &rt, frame_length, sample_rate, true); + // reset state after command vad_state = VadState::WaitingForVoice; silence_frames = 0; audio_buffer.clear(); stt::reset_wake_recognizer(); + stt::reset_speech_recognizer(); // NOW reset, after command is done audio_processing::reset(); ipc::send(IpcEvent::Idle); @@ -116,11 +125,11 @@ fn main_loop(text_cmd_rx: Receiver) -> Result<(), ()> { silence_frames += 1; if silence_frames > silence_threshold { - // silence timeout, back to waiting debug!("VAD: Silence timeout, returning to wait state"); vad_state = VadState::WaitingForVoice; silence_frames = 0; stt::reset_wake_recognizer(); + stt::reset_speech_recognizer(); // reset since we were dual-feeding } } } @@ -140,11 +149,17 @@ fn recognize_command( rt: &tokio::runtime::Runtime, frame_length: usize, sample_rate: usize, + prefed_audio: bool ) { let mut audio_buffer = AudioRingBuffer::new(2.0, frame_length, sample_rate); - let mut vad_state = VadState::WaitingForVoice; + let mut vad_state = if prefed_audio { + VadState::VoiceActive + } else { + VadState::WaitingForVoice + }; let mut silence_frames: u32 = 0; let mut start = SystemTime::now(); + let mut first_recognition = prefed_audio; // longer silence threshold for commands (user might pause to think) // 2 seconds @@ -169,6 +184,13 @@ fn recognize_command( } vad_state = VadState::VoiceActive; silence_frames = 0; + } else { + silence_frames += 1; + + if silence_frames > silence_threshold { + info!("Long silence detected, returning to wake word mode."); + return; + } } } @@ -184,20 +206,51 @@ fn recognize_command( recognized_voice = recognized_voice.to_lowercase(); // check if wake word repeated (reactivate) - let wake_phrase = config::get_wake_phrase(&i18n::get_language()); - if recognized_voice.contains(wake_phrase) { - info!("Wake word detected during chaining, reactivating..."); - voices::play_reply(); - stt::reset_speech_recognizer(); - ipc::send(IpcEvent::Listening); - - // reset for next command - vad_state = VadState::WaitingForVoice; - silence_frames = 0; - start = SystemTime::now(); - audio_buffer.clear(); - continue; + let wake_phrases = config::get_wake_phrases(&i18n::get_language()); + let contains_wake = wake_phrases.iter().any(|wp| recognized_voice.contains(wp)); + + if contains_wake { + // strip the wake word + let mut remaining = recognized_voice.clone(); + for wp in wake_phrases { + remaining = remaining.replace(wp, ""); + } + let remaining = remaining.trim(); + + if remaining.is_empty() { + if first_recognition { + // leftover wake word from dual-feed, just discard it + info!("Discarding initial wake word from prefed audio"); + first_recognition = false; + stt::reset_speech_recognizer(); + voices::play_reply(); + vad_state = VadState::WaitingForVoice; + silence_frames = 0; + start = SystemTime::now(); + audio_buffer.clear(); + continue; + } + + // just wake word, no command - reactivate + info!("Wake word repeated during chaining, reactivating..."); + voices::play_reply(); + stt::reset_speech_recognizer(); + ipc::send(IpcEvent::Listening); + + vad_state = VadState::WaitingForVoice; + silence_frames = 0; + start = SystemTime::now(); + audio_buffer.clear(); + continue; + } else { + // wake word + command in one phrase - execute the command part + info!("Wake word + command during chaining: '{}'", remaining); + recognized_voice = remaining.to_string(); + // fall through to command execution below + } } + + first_recognition = false; // filter activation phrases // for tbr in config::ASSISTANT_PHRASES_TBR { @@ -228,6 +281,7 @@ fn recognize_command( continue; } else { // no chain: return to wake word + info!("No chain, returning to wake word mode."); return; } } diff --git a/crates/jarvis-core/src/config.rs b/crates/jarvis-core/src/config.rs index c29df90..c2daf47 100644 --- a/crates/jarvis-core/src/config.rs +++ b/crates/jarvis-core/src/config.rs @@ -206,29 +206,30 @@ pub const CMS_WAIT_DELAY: std::time::Duration = std::time::Duration::from_secs(1 -pub fn get_wake_phrase(lang: &str) -> &'static str { +pub fn get_wake_phrases(lang: &str) -> &'static [&'static str] { match lang { - "ru" => "джарвис", - "ua" => "джарвіс", - "en" => "jarvis", - _ => "jarvis", + "ru" => &["джарвис", "джервис", "гарвис", "джарви", "гарви"], + "ua" => &["джарвіс", "джервіс"], + "en" => &["jarvis", "jervis"], + _ => &["jarvis"], } } pub fn get_phrases_to_remove(lang: &str) -> &'static [&'static str] { match lang { "ru" => &[ - "джарвис", "сэр", "слушаю сэр", "всегда к услугам", + "джарвис", "джервис", "гарвис", "джарви", "гарви", + "сэр", "слушаю сэр", "всегда к услугам", "произнеси", "ответь", "покажи", "скажи", "давай", "да сэр", "к вашим услугам сэр", "загружаю сэр", ], "ua" => &[ - "джарвіс", "сер", "слухаю сер", "завжди до послуг", + "джарвіс", "джервіс", "сер", "слухаю сер", "завжди до послуг", "скажи", "покажи", "відповідай", "давай", "так сер", "до ваших послуг сер", ], "en" => &[ - "jarvis", "sir", "yes sir", "at your service", + "jarvis", "jervis", "sir", "yes sir", "at your service", "please", "say", "show", "tell", "hey", ], _ => &["jarvis"], diff --git a/crates/jarvis-core/src/intent.rs b/crates/jarvis-core/src/intent.rs index 79f60d5..bec4476 100644 --- a/crates/jarvis-core/src/intent.rs +++ b/crates/jarvis-core/src/intent.rs @@ -14,7 +14,6 @@ pub async fn init(commands: &Vec) -> Result<(), String> { } // already initialized // set default ire type - // @TODO. Make it configurable? IRE_TYPE.set(config::DEFAULT_INTENT_RECOGNITION_ENGINE).unwrap(); // load given recorder diff --git a/crates/jarvis-core/src/listener/vosk.rs b/crates/jarvis-core/src/listener/vosk.rs index 7ef7a58..22160aa 100644 --- a/crates/jarvis-core/src/listener/vosk.rs +++ b/crates/jarvis-core/src/listener/vosk.rs @@ -17,19 +17,28 @@ pub fn data_callback(frame_buffer: &[i16]) -> Option { // language-specific wake phrase let lang = i18n::get_language(); - let wake_phrase = config::get_wake_phrase(&lang); + let wake_phrases = config::get_wake_phrases(&lang); // verify with seqdiff ratio - let wake_chars: Vec = wake_phrase.chars().collect(); - let recognized_chars: Vec = recognized.chars().collect(); - let similarity = seqdiff::ratio(&wake_chars, &recognized_chars); - - info!("Similarity: {:.1}% ('{}' vs '{}')", similarity, recognized, config::VOSK_FETCH_PHRASE); - - if similarity >= config::VOSK_MIN_RATIO { - info!("Wake word activated!"); - return Some(0); + for word in recognized.split_whitespace() { + if word == "[unk]" { + continue; + } + + let word_chars: Vec = word.chars().collect(); + + for wake_phrase in wake_phrases { + let wake_chars: Vec = wake_phrase.chars().collect(); + let similarity = seqdiff::ratio(&wake_chars, &word_chars); + + if similarity >= config::VOSK_MIN_RATIO { + info!("Wake word match: '{}' ~ '{}' ({:.1}%)", word, wake_phrase, similarity); + return Some(0); + } + } } + + // info!("Similarity: {:.1}% ('{}' vs '{}')", similarity, recognized, config::VOSK_FETCH_PHRASE); } None diff --git a/crates/jarvis-core/src/recorder.rs b/crates/jarvis-core/src/recorder.rs index f9a7fe9..7bef81c 100644 --- a/crates/jarvis-core/src/recorder.rs +++ b/crates/jarvis-core/src/recorder.rs @@ -123,7 +123,19 @@ pub fn stop_recording() -> Result<(), ()> { } pub fn get_selected_microphone_index() -> i32 { - DB.get().unwrap().read().microphone + let idx = DB.get().unwrap().read().microphone; + + if idx > 0 { + // validate that this microphone is actually in the list + let devices = get_audio_devices(); + if (idx as usize) >= devices.len() { + warn!("Microphone index {} not found ({} available), falling back to default", + idx, devices.len()); + return -1; + } + } + + idx } pub fn get_audio_devices() -> Vec { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 91d158c..9fd5235 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,7 +12,7 @@ "@svelteuidev/core": "^0.15.7", "@svelteuidev/motion": "^0.15.7", "@tauri-apps/api": "^2.9.1", - "@tauri-apps/plugin-dialog": "^2", + "@tauri-apps/plugin-dialog": "^2.6.0", "@tauri-apps/plugin-fs": "^2", "@tauri-apps/plugin-shell": "^2", "howler": "^2.2.4", @@ -21,7 +21,7 @@ }, "devDependencies": { "@roxi/routify": "^3.6.4", - "@sveltejs/vite-plugin-svelte": "^3.1.0", + "@sveltejs/vite-plugin-svelte": "^3.1.2", "@tauri-apps/cli": "^2", "@tsconfig/svelte": "^5.0.6", "@types/howler": "^2.2.12", @@ -32,7 +32,7 @@ "svelte-preprocess": "^5.1.4", "tslib": "^2.8.1", "typescript": "^5.9.3", - "vite": "^5.4.0", + "vite": "^5.4.21", "vite-tsconfig-paths": "^4.3.2" } }, @@ -40,6 +40,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -477,6 +478,7 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -487,6 +489,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -496,12 +499,14 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1174,7 +1179,6 @@ "integrity": "sha512-cLx0gyUjbdUfQnNCVRi8Itabze/SFQSn7mvF6w/OGZkJRC89sscwMop7CT0hEc+yTZsj5l6RMK6JD5xHS6E9pg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cachewrap": "^0.0.1", "cheap-watch": "^1.0.4", @@ -1230,7 +1234,6 @@ "integrity": "sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^2.1.0", "debug": "^4.3.4", @@ -1271,7 +1274,6 @@ "resolved": "https://registry.npmjs.org/@svelteuidev/composables/-/composables-0.15.7.tgz", "integrity": "sha512-tVA+0bNtsYsJqlpNx9ZArzHFBJYfoKM+nspkv+wzOx40HsCg33MutqNexOvrMYSj5/tSxxBefLQKdwNumErF6Q==", "license": "MIT", - "peer": true, "peerDependencies": { "svelte": ">=3.55.0" } @@ -1527,9 +1529,9 @@ } }, "node_modules/@tauri-apps/plugin-dialog": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.4.2.tgz", - "integrity": "sha512-lNIn5CZuw8WZOn8zHzmFmDSzg5zfohWoa3mdULP0YFh/VogVdMVWZPcWSHlydsiJhRQYaTNSYKN7RmZKE2lCYQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.6.0.tgz", + "integrity": "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==", "license": "MIT OR Apache-2.0", "dependencies": { "@tauri-apps/api": "^2.8.0" @@ -1564,6 +1566,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, "license": "MIT" }, "node_modules/@types/howler": { @@ -1579,7 +1582,6 @@ "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1595,6 +1597,7 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -1621,6 +1624,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -1630,6 +1634,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -1789,6 +1794,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", @@ -1861,6 +1867,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, "license": "MIT", "dependencies": { "mdn-data": "2.0.30", @@ -2120,6 +2127,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" @@ -2409,6 +2417,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.6" @@ -2441,12 +2450,14 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true, "license": "MIT" }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -2456,6 +2467,7 @@ "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true, "license": "CC0-1.0" }, "node_modules/micromatch": { @@ -2703,6 +2715,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -2757,7 +2770,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -2909,7 +2921,6 @@ "integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -2962,6 +2973,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -2984,8 +2996,8 @@ "version": "4.2.20", "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.20.tgz", "integrity": "sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.1", "@jridgewell/sourcemap-codec": "^1.4.15", @@ -3228,7 +3240,6 @@ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", diff --git a/frontend/package.json b/frontend/package.json index 80643ae..856f2b2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,7 +15,7 @@ "@svelteuidev/core": "^0.15.7", "@svelteuidev/motion": "^0.15.7", "@tauri-apps/api": "^2.9.1", - "@tauri-apps/plugin-dialog": "^2", + "@tauri-apps/plugin-dialog": "^2.6.0", "@tauri-apps/plugin-fs": "^2", "@tauri-apps/plugin-shell": "^2", "howler": "^2.2.4", @@ -24,7 +24,7 @@ }, "devDependencies": { "@roxi/routify": "^3.6.4", - "@sveltejs/vite-plugin-svelte": "^3.1.0", + "@sveltejs/vite-plugin-svelte": "^3.1.2", "@tauri-apps/cli": "^2", "@tsconfig/svelte": "^5.0.6", "@types/howler": "^2.2.12", @@ -35,7 +35,7 @@ "svelte-preprocess": "^5.1.4", "tslib": "^2.8.1", "typescript": "^5.9.3", - "vite": "^5.4.0", + "vite": "^5.4.21", "vite-tsconfig-paths": "^4.3.2" } } diff --git a/frontend/vite.config.ts.timestamp-1770509676896-5765e138513238.mjs b/frontend/vite.config.ts.timestamp-1770509676896-5765e138513238.mjs new file mode 100644 index 0000000..cbc86eb --- /dev/null +++ b/frontend/vite.config.ts.timestamp-1770509676896-5765e138513238.mjs @@ -0,0 +1,40 @@ +// vite.config.ts +import { defineConfig } from "file:///D:/Rust/jarvis-app/frontend/node_modules/vite/dist/node/index.js"; +import { svelte } from "file:///D:/Rust/jarvis-app/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/index.js"; +import sveltePreprocess from "file:///D:/Rust/jarvis-app/frontend/node_modules/svelte-preprocess/dist/index.js"; +import tsconfigPaths from "file:///D:/Rust/jarvis-app/frontend/node_modules/vite-tsconfig-paths/dist/index.mjs"; +import routify from "file:///D:/Rust/jarvis-app/frontend/node_modules/@roxi/routify/lib/extra/vite-plugin/vite-plugin.js"; +var vite_config_default = defineConfig({ + plugins: [ + svelte({ + preprocess: [ + sveltePreprocess({ + typescript: true + }) + ], + onwarn: (warning, handler) => { + const { code, frame } = warning; + if (code === "css-unused-selector") + return; + handler(warning); + } + }), + routify(), + tsconfigPaths() + ], + clearScreen: false, + server: { + port: 1420, + strictPort: true + }, + envPrefix: ["VITE_", "TAURI_"], + build: { + target: process.env.TAURI_PLATFORM == "windows" ? "chrome105" : "safari13", + minify: !process.env.TAURI_DEBUG ? "esbuild" : false, + sourcemap: !!process.env.TAURI_DEBUG + } +}); +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJEOlxcXFxSdXN0XFxcXGphcnZpcy1hcHBcXFxcZnJvbnRlbmRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkQ6XFxcXFJ1c3RcXFxcamFydmlzLWFwcFxcXFxmcm9udGVuZFxcXFx2aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRDovUnVzdC9qYXJ2aXMtYXBwL2Zyb250ZW5kL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInZpdGVcIjtcclxuaW1wb3J0IHsgc3ZlbHRlIH0gZnJvbSBcIkBzdmVsdGVqcy92aXRlLXBsdWdpbi1zdmVsdGVcIjtcclxuaW1wb3J0IHN2ZWx0ZVByZXByb2Nlc3MgZnJvbSBcInN2ZWx0ZS1wcmVwcm9jZXNzXCI7XHJcbmltcG9ydCB0c2NvbmZpZ1BhdGhzIGZyb20gJ3ZpdGUtdHNjb25maWctcGF0aHMnXHJcbmltcG9ydCByb3V0aWZ5IGZyb20gJ0Byb3hpL3JvdXRpZnkvdml0ZS1wbHVnaW4nXHJcblxyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoe1xyXG4gIHBsdWdpbnM6IFtcclxuICAgIHN2ZWx0ZSh7XHJcbiAgICAgIHByZXByb2Nlc3M6IFtcclxuICAgICAgICBzdmVsdGVQcmVwcm9jZXNzKHtcclxuICAgICAgICAgIHR5cGVzY3JpcHQ6IHRydWUsXHJcbiAgICAgICAgfSksXHJcbiAgICAgIF0sXHJcbiAgICAgIG9ud2FybjogKHdhcm5pbmcsIGhhbmRsZXIpID0+IHtcclxuICAgICAgICBjb25zdCB7IGNvZGUsIGZyYW1lIH0gPSB3YXJuaW5nO1xyXG4gICAgICAgIGlmIChjb2RlID09PSBcImNzcy11bnVzZWQtc2VsZWN0b3JcIilcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBoYW5kbGVyKHdhcm5pbmcpO1xyXG4gICAgICB9LFxyXG4gICAgfSksXHJcbiAgICByb3V0aWZ5KCksXHJcbiAgICB0c2NvbmZpZ1BhdGhzKClcclxuICBdLFxyXG5cclxuICBjbGVhclNjcmVlbjogZmFsc2UsXHJcbiAgc2VydmVyOiB7XHJcbiAgICBwb3J0OiAxNDIwLFxyXG4gICAgc3RyaWN0UG9ydDogdHJ1ZSxcclxuICB9LFxyXG4gIGVudlByZWZpeDogW1wiVklURV9cIiwgXCJUQVVSSV9cIl0sXHJcbiAgYnVpbGQ6IHtcclxuICAgIHRhcmdldDogcHJvY2Vzcy5lbnYuVEFVUklfUExBVEZPUk0gPT0gXCJ3aW5kb3dzXCIgPyBcImNocm9tZTEwNVwiIDogXCJzYWZhcmkxM1wiLFxyXG4gICAgbWluaWZ5OiAhcHJvY2Vzcy5lbnYuVEFVUklfREVCVUcgPyBcImVzYnVpbGRcIiA6IGZhbHNlLFxyXG4gICAgc291cmNlbWFwOiAhIXByb2Nlc3MuZW52LlRBVVJJX0RFQlVHLFxyXG4gIH0sXHJcbn0pOyJdLAogICJtYXBwaW5ncyI6ICI7QUFBMlEsU0FBUyxvQkFBb0I7QUFDeFMsU0FBUyxjQUFjO0FBQ3ZCLE9BQU8sc0JBQXNCO0FBQzdCLE9BQU8sbUJBQW1CO0FBQzFCLE9BQU8sYUFBYTtBQUVwQixJQUFPLHNCQUFRLGFBQWE7QUFBQSxFQUMxQixTQUFTO0FBQUEsSUFDUCxPQUFPO0FBQUEsTUFDTCxZQUFZO0FBQUEsUUFDVixpQkFBaUI7QUFBQSxVQUNmLFlBQVk7QUFBQSxRQUNkLENBQUM7QUFBQSxNQUNIO0FBQUEsTUFDQSxRQUFRLENBQUMsU0FBUyxZQUFZO0FBQzVCLGNBQU0sRUFBRSxNQUFNLE1BQU0sSUFBSTtBQUN4QixZQUFJLFNBQVM7QUFDVDtBQUVKLGdCQUFRLE9BQU87QUFBQSxNQUNqQjtBQUFBLElBQ0YsQ0FBQztBQUFBLElBQ0QsUUFBUTtBQUFBLElBQ1IsY0FBYztBQUFBLEVBQ2hCO0FBQUEsRUFFQSxhQUFhO0FBQUEsRUFDYixRQUFRO0FBQUEsSUFDTixNQUFNO0FBQUEsSUFDTixZQUFZO0FBQUEsRUFDZDtBQUFBLEVBQ0EsV0FBVyxDQUFDLFNBQVMsUUFBUTtBQUFBLEVBQzdCLE9BQU87QUFBQSxJQUNMLFFBQVEsUUFBUSxJQUFJLGtCQUFrQixZQUFZLGNBQWM7QUFBQSxJQUNoRSxRQUFRLENBQUMsUUFBUSxJQUFJLGNBQWMsWUFBWTtBQUFBLElBQy9DLFdBQVcsQ0FBQyxDQUFDLFFBQVEsSUFBSTtBQUFBLEVBQzNCO0FBQ0YsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K diff --git a/frontend/vite.config.ts.timestamp-1770514438523-d341ca23785658.mjs b/frontend/vite.config.ts.timestamp-1770514438523-d341ca23785658.mjs new file mode 100644 index 0000000..cbc86eb --- /dev/null +++ b/frontend/vite.config.ts.timestamp-1770514438523-d341ca23785658.mjs @@ -0,0 +1,40 @@ +// vite.config.ts +import { defineConfig } from "file:///D:/Rust/jarvis-app/frontend/node_modules/vite/dist/node/index.js"; +import { svelte } from "file:///D:/Rust/jarvis-app/frontend/node_modules/@sveltejs/vite-plugin-svelte/src/index.js"; +import sveltePreprocess from "file:///D:/Rust/jarvis-app/frontend/node_modules/svelte-preprocess/dist/index.js"; +import tsconfigPaths from "file:///D:/Rust/jarvis-app/frontend/node_modules/vite-tsconfig-paths/dist/index.mjs"; +import routify from "file:///D:/Rust/jarvis-app/frontend/node_modules/@roxi/routify/lib/extra/vite-plugin/vite-plugin.js"; +var vite_config_default = defineConfig({ + plugins: [ + svelte({ + preprocess: [ + sveltePreprocess({ + typescript: true + }) + ], + onwarn: (warning, handler) => { + const { code, frame } = warning; + if (code === "css-unused-selector") + return; + handler(warning); + } + }), + routify(), + tsconfigPaths() + ], + clearScreen: false, + server: { + port: 1420, + strictPort: true + }, + envPrefix: ["VITE_", "TAURI_"], + build: { + target: process.env.TAURI_PLATFORM == "windows" ? "chrome105" : "safari13", + minify: !process.env.TAURI_DEBUG ? "esbuild" : false, + sourcemap: !!process.env.TAURI_DEBUG + } +}); +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJEOlxcXFxSdXN0XFxcXGphcnZpcy1hcHBcXFxcZnJvbnRlbmRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkQ6XFxcXFJ1c3RcXFxcamFydmlzLWFwcFxcXFxmcm9udGVuZFxcXFx2aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRDovUnVzdC9qYXJ2aXMtYXBwL2Zyb250ZW5kL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInZpdGVcIjtcclxuaW1wb3J0IHsgc3ZlbHRlIH0gZnJvbSBcIkBzdmVsdGVqcy92aXRlLXBsdWdpbi1zdmVsdGVcIjtcclxuaW1wb3J0IHN2ZWx0ZVByZXByb2Nlc3MgZnJvbSBcInN2ZWx0ZS1wcmVwcm9jZXNzXCI7XHJcbmltcG9ydCB0c2NvbmZpZ1BhdGhzIGZyb20gJ3ZpdGUtdHNjb25maWctcGF0aHMnXHJcbmltcG9ydCByb3V0aWZ5IGZyb20gJ0Byb3hpL3JvdXRpZnkvdml0ZS1wbHVnaW4nXHJcblxyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoe1xyXG4gIHBsdWdpbnM6IFtcclxuICAgIHN2ZWx0ZSh7XHJcbiAgICAgIHByZXByb2Nlc3M6IFtcclxuICAgICAgICBzdmVsdGVQcmVwcm9jZXNzKHtcclxuICAgICAgICAgIHR5cGVzY3JpcHQ6IHRydWUsXHJcbiAgICAgICAgfSksXHJcbiAgICAgIF0sXHJcbiAgICAgIG9ud2FybjogKHdhcm5pbmcsIGhhbmRsZXIpID0+IHtcclxuICAgICAgICBjb25zdCB7IGNvZGUsIGZyYW1lIH0gPSB3YXJuaW5nO1xyXG4gICAgICAgIGlmIChjb2RlID09PSBcImNzcy11bnVzZWQtc2VsZWN0b3JcIilcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBoYW5kbGVyKHdhcm5pbmcpO1xyXG4gICAgICB9LFxyXG4gICAgfSksXHJcbiAgICByb3V0aWZ5KCksXHJcbiAgICB0c2NvbmZpZ1BhdGhzKClcclxuICBdLFxyXG5cclxuICBjbGVhclNjcmVlbjogZmFsc2UsXHJcbiAgc2VydmVyOiB7XHJcbiAgICBwb3J0OiAxNDIwLFxyXG4gICAgc3RyaWN0UG9ydDogdHJ1ZSxcclxuICB9LFxyXG4gIGVudlByZWZpeDogW1wiVklURV9cIiwgXCJUQVVSSV9cIl0sXHJcbiAgYnVpbGQ6IHtcclxuICAgIHRhcmdldDogcHJvY2Vzcy5lbnYuVEFVUklfUExBVEZPUk0gPT0gXCJ3aW5kb3dzXCIgPyBcImNocm9tZTEwNVwiIDogXCJzYWZhcmkxM1wiLFxyXG4gICAgbWluaWZ5OiAhcHJvY2Vzcy5lbnYuVEFVUklfREVCVUcgPyBcImVzYnVpbGRcIiA6IGZhbHNlLFxyXG4gICAgc291cmNlbWFwOiAhIXByb2Nlc3MuZW52LlRBVVJJX0RFQlVHLFxyXG4gIH0sXHJcbn0pOyJdLAogICJtYXBwaW5ncyI6ICI7QUFBMlEsU0FBUyxvQkFBb0I7QUFDeFMsU0FBUyxjQUFjO0FBQ3ZCLE9BQU8sc0JBQXNCO0FBQzdCLE9BQU8sbUJBQW1CO0FBQzFCLE9BQU8sYUFBYTtBQUVwQixJQUFPLHNCQUFRLGFBQWE7QUFBQSxFQUMxQixTQUFTO0FBQUEsSUFDUCxPQUFPO0FBQUEsTUFDTCxZQUFZO0FBQUEsUUFDVixpQkFBaUI7QUFBQSxVQUNmLFlBQVk7QUFBQSxRQUNkLENBQUM7QUFBQSxNQUNIO0FBQUEsTUFDQSxRQUFRLENBQUMsU0FBUyxZQUFZO0FBQzVCLGNBQU0sRUFBRSxNQUFNLE1BQU0sSUFBSTtBQUN4QixZQUFJLFNBQVM7QUFDVDtBQUVKLGdCQUFRLE9BQU87QUFBQSxNQUNqQjtBQUFBLElBQ0YsQ0FBQztBQUFBLElBQ0QsUUFBUTtBQUFBLElBQ1IsY0FBYztBQUFBLEVBQ2hCO0FBQUEsRUFFQSxhQUFhO0FBQUEsRUFDYixRQUFRO0FBQUEsSUFDTixNQUFNO0FBQUEsSUFDTixZQUFZO0FBQUEsRUFDZDtBQUFBLEVBQ0EsV0FBVyxDQUFDLFNBQVMsUUFBUTtBQUFBLEVBQzdCLE9BQU87QUFBQSxJQUNMLFFBQVEsUUFBUSxJQUFJLGtCQUFrQixZQUFZLGNBQWM7QUFBQSxJQUNoRSxRQUFRLENBQUMsUUFBUSxJQUFJLGNBQWMsWUFBWTtBQUFBLElBQy9DLFdBQVcsQ0FBQyxDQUFDLFFBQVEsSUFBSTtBQUFBLEVBQzNCO0FBQ0YsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K diff --git a/post_build.py b/post_build.py index 39a5e15..5a62ae9 100644 --- a/post_build.py +++ b/post_build.py @@ -17,11 +17,16 @@ SOURCE = ( ("resources/keywords/", "resources/keywords/"), ("resources/rustpotter/", "resources/rustpotter/"), ("resources/sound/", "resources/sound/"), + + # vosk ("lib/windows/amd64/libgcc_s_seh-1.dll", None), ("lib/windows/amd64/libstdc++-6.dll", None), ("lib/windows/amd64/libvosk.dll", None), ("lib/windows/amd64/libvosk.lib", None), - ("lib/windows/amd64/libwinpthread-1.dll", None) + ("lib/windows/amd64/libwinpthread-1.dll", None), + + # pvrecorder + ("lib/windows/amd64/libpv_recorder.dll", None), ) TARGET_DIRS = (