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
84
resources/commands/cooking/timer.lua
Normal file
84
resources/commands/cooking/timer.lua
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
-- Cooking timer — recognise the dish in the phrase and schedule a "ready!"
|
||||
-- reminder for the right number of minutes. Falls through to a generic
|
||||
-- "couldn't recognise" reply if nothing matched.
|
||||
--
|
||||
-- The duration table is opinionated but covers the common Russian kitchen
|
||||
-- staples. Power users can override via `recipes.txt` (TODO future) — for
|
||||
-- now, edit this file or use the generic `reminders/set` pack.
|
||||
|
||||
local lang = jarvis.context.language
|
||||
local phrase = (jarvis.context.phrase or ""):lower()
|
||||
|
||||
-- pattern -> { minutes, ru_label, en_label }
|
||||
local recipes = {
|
||||
{ "чайник", 4, "чайник", "kettle" },
|
||||
{ "boiling water",4, "вода", "boiling water" },
|
||||
{ "французск", 4, "френч-пресс", "french press" },
|
||||
{ "french press", 4, "френч-пресс", "french press" },
|
||||
{ "чай", 5, "чай", "tea" },
|
||||
{ "brewing tea", 5, "чай", "tea" },
|
||||
{ "омлет", 5, "омлет", "omelette" },
|
||||
{ "омлеt", 5, "омлет", "omelette" }, -- mis-STT guard
|
||||
{ "яичниц", 5, "яичница", "fried eggs" },
|
||||
{ "frying eggs", 5, "яичница", "fried eggs" },
|
||||
{ "frying omelet",5, "омлет", "omelette" },
|
||||
{ "кофе", 5, "кофе", "coffee" },
|
||||
{ "brewing coff", 5, "кофе", "coffee" },
|
||||
{ "яйц", 8, "яйца", "eggs" },
|
||||
{ "boiling eggs", 8, "яйца", "eggs" },
|
||||
{ "макарон", 10, "макароны", "pasta" },
|
||||
{ "паст", 10, "паста", "pasta" },
|
||||
{ "cooking pasta",10, "паста", "pasta" },
|
||||
{ "boiling pasta",10, "паста", "pasta" },
|
||||
{ "рис", 18, "рис", "rice" },
|
||||
{ "cooking rice", 18, "рис", "rice" },
|
||||
{ "греч", 20, "гречка", "buckwheat" },
|
||||
{ "каш", 20, "каша", "porridge" },
|
||||
{ "porridge", 20, "каша", "porridge" },
|
||||
{ "картош", 22, "картошка", "potatoes" },
|
||||
{ "пицц", 15, "пицца", "pizza" },
|
||||
{ "baking pizza", 15, "пицца", "pizza" },
|
||||
{ "куриц", 35, "курица", "chicken" },
|
||||
{ "chicken", 35, "курица", "chicken" },
|
||||
}
|
||||
|
||||
local matched_minutes, label_ru, label_en = nil, nil, nil
|
||||
for _, r in ipairs(recipes) do
|
||||
if phrase:find(r[1], 1, true) then
|
||||
matched_minutes, label_ru, label_en = r[2], r[3], r[4]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not matched_minutes then
|
||||
return jarvis.cmd.not_found(lang == "ru"
|
||||
and "Не понял, что ты готовишь, сэр."
|
||||
or "I didn't catch what you're cooking, sir.")
|
||||
end
|
||||
|
||||
local label = (lang == "ru") and label_ru or label_en
|
||||
local speak_text = (lang == "ru" and "Сэр, " or "Sir, ")
|
||||
.. label .. (lang == "ru" and " готов." or " is ready.")
|
||||
|
||||
local ok, err = pcall(function()
|
||||
jarvis.scheduler.add({
|
||||
name = (lang == "ru" and "Кухня: " or "Cooking: ") .. label,
|
||||
schedule = "in " .. tostring(matched_minutes) .. " minutes",
|
||||
action = { type = "speak", text = speak_text },
|
||||
})
|
||||
end)
|
||||
if not ok then
|
||||
jarvis.log("error", "cooking timer: scheduler.add failed: " .. tostring(err))
|
||||
return jarvis.cmd.error(lang == "ru" and "Не получилось поставить таймер."
|
||||
or "Couldn't set timer.")
|
||||
end
|
||||
|
||||
jarvis.system.notify(
|
||||
lang == "ru" and "Таймер" or "Timer",
|
||||
string.format("%s — %d мин", label, matched_minutes)
|
||||
)
|
||||
|
||||
return jarvis.cmd.ok(string.format(lang == "ru"
|
||||
and "Хорошо, напомню через %d минут когда %s будет готов."
|
||||
or "Right — I'll remind you in %d minutes when %s is ready.",
|
||||
matched_minutes, label))
|
||||
Loading…
Add table
Add a link
Reference in a new issue