From a6a098de15c8dfd0ca2d5da52778c6b792fc7529 Mon Sep 17 00:00:00 2001 From: Bossiara13 <236771060+DmitryBykov-ISPO@users.noreply.github.com> Date: Fri, 15 May 2026 17:37:32 +0300 Subject: [PATCH] =?UTF-8?q?feat(ipc):=20SwitchLlm=20+=20ReloadLlm=20+=20Qu?= =?UTF-8?q?eryHealth=20=E2=80=94=20daemon=20hot-swap=20+=20state=20snapsho?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the "GUI shows GUI process state, not daemon's" gap. Now GUI can: 1. Tell the daemon to swap LLM backend via IPC (so the running listener uses the new backend immediately, not just the GUI process). 2. Tell the daemon to re-read llm_backend from settings DB after GUI persists a choice independently. 3. Query the daemon's true runtime state (TTS/LLM/profile/memory/scheduler counts/language/version) for an honest footer + diagnostics view. IpcAction (new variants) - SwitchLlm { backend: String } — daemon calls llm::swap_to(parse(backend)) - ReloadLlm — daemon calls llm::init_global() to re-read DB - QueryHealth — daemon responds with HealthSnapshot IpcEvent (new variant) - HealthSnapshot { tts_backend, llm_backend, llm_model, active_profile, memory_facts, scheduled_tasks, language, version } jarvis-app main.rs - Imports IpcEvent (was only IpcAction before). - Three new match arms in ipc action handler — all use existing globals, no new state needed. Next step (TODO): wire GUI's set_llm_backend Tauri command to ALSO fire IpcAction::SwitchLlm so daemon stays in sync. And replace Footer.svelte's get_active_backends call with QueryHealth over IPC. Build: cargo build --release -p jarvis-app -p jarvis-gui green. Tests: 62/62 pass (unchanged — IPC variants don't add testable logic). --- crates/jarvis-app/src/main.rs | 32 +++++++++++++++++++++++++++- crates/jarvis-core/src/ipc/events.rs | 22 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/crates/jarvis-app/src/main.rs b/crates/jarvis-app/src/main.rs index fb82dc7..852be15 100644 --- a/crates/jarvis-app/src/main.rs +++ b/crates/jarvis-app/src/main.rs @@ -6,7 +6,7 @@ use std::sync::mpsc; // include core use jarvis_core::{ audio, audio_processing, commands, config, db, listener, recorder, stt, intent, - ipc::{self, IpcAction}, + ipc::{self, IpcAction, IpcEvent}, i18n, voices, models, APP_CONFIG_DIR, APP_LOG_DIR, COMMANDS_LIST, DB, }; @@ -194,6 +194,36 @@ fn main() -> Result<(), String> { IpcAction::Ping => { // handled internally by server } + IpcAction::SwitchLlm { backend } => { + info!("Received SwitchLlm IPC: {}", backend); + if let Some(b) = jarvis_core::llm::parse_backend(&backend) { + match jarvis_core::llm::swap_to(b) { + Ok(name) => info!("LLM swapped via IPC → {}", name), + Err(e) => warn!("LLM swap via IPC failed: {}", e), + } + } else { + warn!("SwitchLlm: unknown backend '{}'", backend); + } + } + IpcAction::ReloadLlm => { + info!("Received ReloadLlm IPC — reading DB and re-initialising"); + if let Err(e) = jarvis_core::llm::init_global() { + warn!("LLM reload failed: {}", e); + } + } + IpcAction::QueryHealth => { + let model = jarvis_core::llm::current().map(|c| c.model().to_string()); + ipc::send(IpcEvent::HealthSnapshot { + tts_backend: jarvis_core::tts::backend().name().to_string(), + llm_backend: jarvis_core::llm::current_backend_name().to_string(), + llm_model: model, + active_profile: jarvis_core::profiles::active_name(), + memory_facts: jarvis_core::long_term_memory::all().len(), + scheduled_tasks: jarvis_core::scheduler::list().len(), + language: jarvis_core::i18n::get_language(), + version: config::APP_VERSION.map(|s| s.to_string()), + }); + } _ => {} } }); diff --git a/crates/jarvis-core/src/ipc/events.rs b/crates/jarvis-core/src/ipc/events.rs index 7f76f72..afe2e57 100644 --- a/crates/jarvis-core/src/ipc/events.rs +++ b/crates/jarvis-core/src/ipc/events.rs @@ -36,6 +36,18 @@ pub enum IpcEvent { // request GUI to reveal/focus window RevealWindow, + + // Snapshot of daemon's runtime state (response to QueryHealth). + HealthSnapshot { + tts_backend: String, + llm_backend: String, + llm_model: Option, + active_profile: String, + memory_facts: usize, + scheduled_tasks: usize, + language: String, + version: Option, + }, } // Actions sent from GUI to jarvis-app @@ -56,4 +68,14 @@ pub enum IpcAction { // Execute text command TextCommand { text: String }, + + // Daemon-side LLM hot-swap (GUI's set_llm_backend should fire this too + // so the running daemon picks the new backend, not just the GUI process). + SwitchLlm { backend: String }, + + // Reload LLM backend from settings DB (after GUI changed it independently). + ReloadLlm, + + // Request a health snapshot — daemon responds via IpcEvent::HealthSnapshot. + QueryHealth, } \ No newline at end of file