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.
84 lines
3.9 KiB
Lua
84 lines
3.9 KiB
Lua
-- 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))
|