feat: persist LLM/TTS backend choice + reset/repeat context + quick-search + diagnostics
Closes the UX hole I created in 5c72450: voice-swap to Ollama used to vanish
after restart. Plus P0.3 (long-standing roadmap item) and two new packs.
Persistent backend choice (crates/jarvis-core/src/db/structs.rs)
- Settings struct gains llm_backend + tts_backend fields (both String,
"" / "auto" = follow env/auto-detect).
- set("llm_backend", "groq"|"ollama"|"auto") validates input.
- llm::init_global() reads DB first, then JARVIS_LLM env, then auto-detect.
- llm::swap_to() now persists the choice via db::save_settings.
- Voice swap "переключись на локальный" now survives restart.
Shared conversation history (P0.3, crates/jarvis-core/src/llm/mod.rs)
- HISTORY: Lazy<RwLock<Option<ConversationHistory>>> singleton.
- Helpers: init_history, history_push_user, history_push_assistant,
history_snapshot, history_clear, history_pop_last_user, history_last_assistant.
- llm_fallback migrated off its own Mutex<History> — now reads/writes shared.
- ConversationHistory gains last_assistant() method.
New Lua APIs
- jarvis.llm_reset() → clear conversation turns (keeps system prompt).
- jarvis.llm_last_reply() → string or nil (last assistant message text).
- jarvis.health() → debug table {tts_backend, llm_backend, llm_model,
active_profile, memory_facts, scheduled_tasks,
language, voice, microphone, vosk_model,
noise_suppression}. No secrets included.
New voice packs
- resources/commands/llm_context/ (P0.3)
* "сбрось контекст" / "забудь разговор" → llm.reset
* "повтори последнее" / "повтори ответ" → llm.repeat (uses last_assistant)
- resources/commands/quick_search/ (imba P1 item)
* "найди в гугле <X>" / "загугли <X>"
* Uses DuckDuckGo Instant Answer API (api.duckduckgo.com, no key required).
Pulls AbstractText or RelatedTopics into LLM prompt; falls back to pure
LLM knowledge if DDG returns nothing useful. Speaks 2-4 sentence answer.
- resources/commands/diagnostics/
* "диагностика" / "доложи о себе" / "статус"
* Reads jarvis.health() and speaks a one-line summary. Useful when
debugging — user can read out their current state for a bug report.
Build: cargo build --release -p jarvis-app -p jarvis-gui green.
Tests: 52/52 jarvis-core unit tests pass.
This commit is contained in:
parent
5c7245012e
commit
385bd5c8ce
15 changed files with 413 additions and 37 deletions
|
|
@ -12,4 +12,5 @@ pub mod memory;
|
|||
pub mod profile;
|
||||
pub mod vision;
|
||||
pub mod scheduler;
|
||||
pub mod cmd;
|
||||
pub mod cmd;
|
||||
pub mod health;
|
||||
50
crates/jarvis-core/src/lua/api/health.rs
Normal file
50
crates/jarvis-core/src/lua/api/health.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//! `jarvis.health()` — debug snapshot of active runtime state.
|
||||
//!
|
||||
//! Returns a table that can be JSON-encoded for bug reports. Doesn't include
|
||||
//! secrets (no API keys, no LLM history content).
|
||||
//!
|
||||
//! Example use from Lua:
|
||||
//! local h = jarvis.health()
|
||||
//! for k, v in pairs(h) do print(k, v) end
|
||||
|
||||
use mlua::{Lua, Table};
|
||||
|
||||
pub fn register(lua: &Lua, jarvis: &Table) -> mlua::Result<()> {
|
||||
let health_fn = lua.create_function(|lua, ()| {
|
||||
let t = lua.create_table()?;
|
||||
|
||||
// TTS
|
||||
t.set("tts_backend", crate::tts::backend().name())?;
|
||||
|
||||
// LLM
|
||||
t.set("llm_backend", crate::llm::current_backend_name())?;
|
||||
if let Some(c) = crate::llm::current() {
|
||||
t.set("llm_model", c.model().to_string())?;
|
||||
}
|
||||
|
||||
// Profile
|
||||
t.set("active_profile", crate::profiles::active_name())?;
|
||||
|
||||
// Memory size
|
||||
t.set("memory_facts", crate::long_term_memory::all().len())?;
|
||||
|
||||
// Scheduler size
|
||||
t.set("scheduled_tasks", crate::scheduler::list().len())?;
|
||||
|
||||
// Language
|
||||
t.set("language", crate::i18n::get_language())?;
|
||||
|
||||
// Voice from settings
|
||||
if let Some(db) = crate::DB.get() {
|
||||
let s = db.read();
|
||||
t.set("voice", s.voice.clone())?;
|
||||
t.set("microphone", s.microphone)?;
|
||||
t.set("vosk_model", s.vosk_model.clone())?;
|
||||
t.set("noise_suppression", format!("{:?}", s.noise_suppression))?;
|
||||
}
|
||||
|
||||
Ok(t)
|
||||
})?;
|
||||
jarvis.set("health", health_fn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -98,5 +98,25 @@ pub fn register(lua: &Lua, jarvis: &Table) -> mlua::Result<()> {
|
|||
})?;
|
||||
jarvis.set("llm_switch", switch_fn)?;
|
||||
|
||||
// Clear conversation turns (keeps system prompt). Returns true if history was
|
||||
// initialised, false if LLM is not configured.
|
||||
let reset_fn = lua.create_function(|_, ()| {
|
||||
llm::history_clear();
|
||||
Ok(true)
|
||||
})?;
|
||||
jarvis.set("llm_reset", reset_fn)?;
|
||||
|
||||
// Return the most recent assistant message text, or nil.
|
||||
let last_fn = lua.create_function(|lua, ()| {
|
||||
match llm::history_last_assistant() {
|
||||
Some(text) => {
|
||||
let s = lua.create_string(text)?;
|
||||
Ok(Value::String(s))
|
||||
}
|
||||
None => Ok(Value::Nil),
|
||||
}
|
||||
})?;
|
||||
jarvis.set("llm_last_reply", last_fn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ impl LuaEngine {
|
|||
api::profile::register(&self.lua, &jarvis)?;
|
||||
api::scheduler::register(&self.lua, &jarvis)?;
|
||||
api::cmd::register(&self.lua, &jarvis)?;
|
||||
api::health::register(&self.lua, &jarvis)?;
|
||||
|
||||
// sandbox-controlled APIs
|
||||
if self.sandbox.allows_http() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue