feat: Wave 6 — focus mode, cooking timer, memory admin
Focus mode (`focus/`):
- focus.start ("режим фокуса" / "focus mode"): three side-effects in one
voice trigger:
1. switch profile to "work" (silences fun/banter)
2. enable Windows Focus Assist via registry tweak (QuietHours key)
3. schedule a stretch reminder in 50 minutes through the persistent
scheduler — so it survives daemon restart
- focus.stop: undoes all three, including cancelling pending stretch
reminders by matching their scheduler name. Best-effort: any one
failing doesn't block the others.
Cooking timer (`cooking/`):
- Recognises 16+ dish names (чай, кофе, омлет, яйца, макароны, паста,
рис, гречка, картошка, курица, пицца, etc.) and starts a preset-
duration scheduler reminder ("Сэр, чай готов.").
- Single Lua script, table-driven — adding a recipe is one line.
- EN phrases for the same dishes ("boiling pasta", "frying eggs", ...).
Memory admin (`memory_admin/`):
- memory_admin.count → speak fact count with full RU pluralisation.
- memory_admin.list → speak 5 most-recent + toast the rest.
- memory_admin.wipe → ONLY fires on "точно забудь все" prefix (not bare
"забудь все") so we can't disaster-wipe by accident.
- Adds `long_term_memory::clear_all() -> usize` returning removed count
+ Lua binding `jarvis.memory.clear_all()`.
- One extra unit test for `clear_all`.
Tests: 139 → 140 (+1). Pack count: 92 → 95.
This commit is contained in:
parent
df799b6cd2
commit
8f46bd735a
11 changed files with 467 additions and 0 deletions
|
|
@ -205,6 +205,24 @@ pub fn forget(key: &str) -> bool {
|
|||
removed
|
||||
}
|
||||
|
||||
/// Wipe all stored facts. Returns the count of records removed.
|
||||
/// Voice commands call this only after a confirmation prefix
|
||||
/// ("точно забудь все" — not just "забудь все") to avoid disasters.
|
||||
pub fn clear_all() -> usize {
|
||||
let Some(state) = STATE.get() else { return 0; };
|
||||
let n = {
|
||||
let mut store = state.store.write();
|
||||
let n = store.entries.len();
|
||||
store.entries.clear();
|
||||
n
|
||||
};
|
||||
if n > 0 {
|
||||
persist(state);
|
||||
warn!("Memory: WIPED all {} facts", n);
|
||||
}
|
||||
n
|
||||
}
|
||||
|
||||
/// Snapshot of all records (for debug / GUI display).
|
||||
pub fn all() -> Vec<MemoryRecord> {
|
||||
let Some(state) = STATE.get() else { return Vec::new(); };
|
||||
|
|
@ -337,4 +355,12 @@ mod tests {
|
|||
assert_eq!(back.entries.len(), 2);
|
||||
assert_eq!(back.entries.get("key1").unwrap().value, "val1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clear_all_returns_zero_when_state_uninit() {
|
||||
// STATE may or may not be initialised depending on test order; the
|
||||
// public function still needs to return safely (and 0) in either case.
|
||||
// We just exercise the code path — exact count depends on global state.
|
||||
let _ = clear_all();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,12 +56,22 @@ pub fn register(lua: &Lua, jarvis: &Table) -> mlua::Result<()> {
|
|||
let row = lua.create_table()?;
|
||||
row.set("key", h.key.clone())?;
|
||||
row.set("value", h.value.clone())?;
|
||||
row.set("created_at", h.created_at)?;
|
||||
row.set("last_used_at", h.last_used_at)?;
|
||||
row.set("use_count", h.use_count)?;
|
||||
arr.set(i + 1, row)?;
|
||||
}
|
||||
Ok(arr)
|
||||
})?;
|
||||
mem.set("all", all)?;
|
||||
|
||||
// Wipe ALL memory. Returns count of removed facts. Voice packs should
|
||||
// only call this behind a deliberate phrase like "точно забудь всё".
|
||||
let clear_all = lua.create_function(|_, ()| {
|
||||
Ok(long_term_memory::clear_all())
|
||||
})?;
|
||||
mem.set("clear_all", clear_all)?;
|
||||
|
||||
jarvis.set("memory", mem)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue