feat(gui): wire Footer + Settings to daemon over IPC (closes the gap from a6a098d)
a6a098d added daemon-side IPC handlers (SwitchLlm, ReloadLlm, QueryHealth)
but the GUI was still talking only to its own process. This commit wires
the frontend to actually use those handlers.
frontend/src/lib/ipc.ts
- New DaemonHealth interface + daemonHealth: writable<DaemonHealth | null>.
- handleEvent: "health_snapshot" case fills daemonHealth from daemon's IpcEvent.
- New senders:
switchDaemonLlm(backend) → action "switch_llm"
reloadDaemonLlm() → action "reload_llm"
queryDaemonHealth() → action "query_health"
frontend/src/stores.ts
- Re-exports daemonHealth + the three new senders + DaemonHealth type.
frontend/src/components/Footer.svelte
- Polls every 5s but PREFERS IPC: if daemon connected, calls queryDaemonHealth
(snapshot arrives via daemonHealth store).
- Falls back to invoke("get_active_backends") if daemon offline — shows
GUI-process view in that case, with the chip tooltip distinguishing
"daemon" vs "gui-process" source.
frontend/src/routes/settings/index.svelte (AI Backends tab)
- applyLlmBackend now ALSO fires switchDaemonLlm so the running listener
picks the new backend without restart.
- "Auto" (empty) path calls reloadDaemonLlm so daemon re-reads DB.
End-to-end flow now:
GUI dropdown → set_llm_backend (Tauri, persists DB + swaps GUI proc)
↘ switchDaemonLlm (IPC, swaps daemon proc too)
↘ daemon emits health_snapshot on next QueryHealth
↘ daemonHealth store updates
↘ Footer chips re-render with new state
Build: cargo build --release -p jarvis-gui green.
This commit is contained in:
parent
a6a098de15
commit
a2dfadf5c1
4 changed files with 90 additions and 6 deletions
|
|
@ -2,7 +2,10 @@
|
|||
import { onMount, onDestroy } from "svelte"
|
||||
import { invoke } from "@tauri-apps/api/core"
|
||||
|
||||
import { appInfo, translations, translate } from "@/stores"
|
||||
import {
|
||||
appInfo, translations, translate,
|
||||
daemonHealth, ipcConnected, queryDaemonHealth,
|
||||
} from "@/stores"
|
||||
|
||||
$: t = (key: string) => translate($translations, key)
|
||||
|
||||
|
|
@ -29,10 +32,30 @@
|
|||
|
||||
let backends: ActiveBackends | null = null
|
||||
let pollId: ReturnType<typeof setInterval> | null = null
|
||||
let connected = false
|
||||
|
||||
ipcConnected.subscribe(v => { connected = v })
|
||||
daemonHealth.subscribe(h => {
|
||||
if (h) {
|
||||
backends = {
|
||||
tts: h.tts_backend,
|
||||
llm: h.llm_backend,
|
||||
llm_model: h.llm_model,
|
||||
profile: h.active_profile,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
async function refreshBackends() {
|
||||
// Prefer IPC — daemon's actual state.
|
||||
if (connected) {
|
||||
queryDaemonHealth() // response arrives via daemonHealth store
|
||||
return
|
||||
}
|
||||
// Fallback to GUI-process view if daemon offline.
|
||||
try {
|
||||
backends = await invoke<ActiveBackends>("get_active_backends")
|
||||
const fallback = await invoke<ActiveBackends>("get_active_backends")
|
||||
if (!backends) backends = fallback
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
|
|
@ -49,9 +72,10 @@
|
|||
|
||||
function chipTitle(key: "tts" | "llm"): string {
|
||||
if (!backends) return ""
|
||||
if (key === "tts") return `TTS backend: ${backends.tts}`
|
||||
const src = connected ? "daemon" : "gui-process"
|
||||
if (key === "tts") return `TTS backend: ${backends.tts} (${src})`
|
||||
const model = backends.llm_model ? ` (${backends.llm_model})` : ""
|
||||
return `LLM backend: ${backends.llm}${model}`
|
||||
return `LLM backend: ${backends.llm}${model} (${src})`
|
||||
}
|
||||
|
||||
function chipLabel(value: string): string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue