feat(ipc): SwitchLlm + ReloadLlm + QueryHealth — daemon hot-swap + state snapshot
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).
This commit is contained in:
parent
9488190d35
commit
a6a098de15
2 changed files with 53 additions and 1 deletions
|
|
@ -6,7 +6,7 @@ use std::sync::mpsc;
|
||||||
// include core
|
// include core
|
||||||
use jarvis_core::{
|
use jarvis_core::{
|
||||||
audio, audio_processing, commands, config, db, listener, recorder, stt, intent,
|
audio, audio_processing, commands, config, db, listener, recorder, stt, intent,
|
||||||
ipc::{self, IpcAction},
|
ipc::{self, IpcAction, IpcEvent},
|
||||||
i18n, voices, models,
|
i18n, voices, models,
|
||||||
APP_CONFIG_DIR, APP_LOG_DIR, COMMANDS_LIST, DB,
|
APP_CONFIG_DIR, APP_LOG_DIR, COMMANDS_LIST, DB,
|
||||||
};
|
};
|
||||||
|
|
@ -194,6 +194,36 @@ fn main() -> Result<(), String> {
|
||||||
IpcAction::Ping => {
|
IpcAction::Ping => {
|
||||||
// handled internally by server
|
// 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()),
|
||||||
|
});
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,18 @@ pub enum IpcEvent {
|
||||||
|
|
||||||
// request GUI to reveal/focus window
|
// request GUI to reveal/focus window
|
||||||
RevealWindow,
|
RevealWindow,
|
||||||
|
|
||||||
|
// Snapshot of daemon's runtime state (response to QueryHealth).
|
||||||
|
HealthSnapshot {
|
||||||
|
tts_backend: String,
|
||||||
|
llm_backend: String,
|
||||||
|
llm_model: Option<String>,
|
||||||
|
active_profile: String,
|
||||||
|
memory_facts: usize,
|
||||||
|
scheduled_tasks: usize,
|
||||||
|
language: String,
|
||||||
|
version: Option<String>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actions sent from GUI to jarvis-app
|
// Actions sent from GUI to jarvis-app
|
||||||
|
|
@ -56,4 +68,14 @@ pub enum IpcAction {
|
||||||
|
|
||||||
// Execute text command
|
// Execute text command
|
||||||
TextCommand { text: String },
|
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,
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue