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
52
resources/commands/focus/command.toml
Normal file
52
resources/commands/focus/command.toml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Focus mode — combines three things real Jarvis would do for a deep-work session:
|
||||
# 1. switch active profile to "work" (mutes the noise commands)
|
||||
# 2. enable Windows Focus Assist via PowerShell
|
||||
# 3. schedule a break reminder for 50 minutes (with 10-min stretch reminder)
|
||||
# All in one voice trigger.
|
||||
|
||||
[[commands]]
|
||||
id = "focus.start"
|
||||
type = "lua"
|
||||
script = "start.lua"
|
||||
sandbox = "full"
|
||||
timeout = 5000
|
||||
|
||||
[commands.phrases]
|
||||
ru = [
|
||||
"режим фокуса",
|
||||
"включи фокус",
|
||||
"сосредоточиться",
|
||||
"не отвлекай",
|
||||
"режим работы",
|
||||
"хочу поработать",
|
||||
]
|
||||
en = [
|
||||
"focus mode",
|
||||
"enable focus",
|
||||
"do not disturb",
|
||||
"deep work",
|
||||
"let me focus",
|
||||
]
|
||||
|
||||
|
||||
[[commands]]
|
||||
id = "focus.stop"
|
||||
type = "lua"
|
||||
script = "stop.lua"
|
||||
sandbox = "full"
|
||||
timeout = 5000
|
||||
|
||||
[commands.phrases]
|
||||
ru = [
|
||||
"выключи фокус",
|
||||
"выключи режим фокуса",
|
||||
"закончил работать",
|
||||
"отключи не отвлекай",
|
||||
"верни обычный режим",
|
||||
]
|
||||
en = [
|
||||
"exit focus",
|
||||
"stop focus",
|
||||
"disable focus",
|
||||
"i'm done working",
|
||||
]
|
||||
65
resources/commands/focus/start.lua
Normal file
65
resources/commands/focus/start.lua
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
-- Enter focus mode — three side-effects bundled into one voice trigger:
|
||||
-- 1. activate "work" profile (silences fun/games/banter commands)
|
||||
-- 2. enable Windows Focus Assist (Quiet Hours) via registry tweak
|
||||
-- 3. schedule a "стретчинг" reminder in 50 minutes via the persistent scheduler
|
||||
--
|
||||
-- All three are independent — if one fails, the rest still happen.
|
||||
|
||||
local lang = jarvis.context.language
|
||||
|
||||
local report = {}
|
||||
|
||||
-- 1) Profile switch (best effort)
|
||||
local ok1, err1 = pcall(function() jarvis.profile.set("work") end)
|
||||
if ok1 then
|
||||
table.insert(report, lang == "ru" and "профиль 'работа'" or "work profile")
|
||||
else
|
||||
jarvis.log("warn", "focus.start: profile.set failed: " .. tostring(err1))
|
||||
end
|
||||
|
||||
-- 2) Windows Focus Assist: writes the registry key Windows uses for
|
||||
-- "Priority only" mode. This is the same key Windows 11 toggles when you
|
||||
-- flip Focus on/off via the Action Center.
|
||||
local ps = [[
|
||||
$key = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.QuietHours'
|
||||
if (-not (Test-Path $key)) { New-Item -Path $key -Force | Out-Null }
|
||||
Set-ItemProperty -Path $key -Name 'NOC_GLOBAL_SETTING_TOASTS_ENABLED' -Value 0 -Type DWord
|
||||
Write-Output 'fa-on'
|
||||
]]
|
||||
local cmd = 'powershell -NoProfile -ExecutionPolicy Bypass -Command "& {'
|
||||
.. ps:gsub('\r?\n', '; '):gsub('"', '\\"')
|
||||
.. '}"'
|
||||
local res = jarvis.system.exec(cmd)
|
||||
if res.success and (res.stdout or ""):find("fa%-on") then
|
||||
table.insert(report, lang == "ru" and "уведомления выключены" or "notifications muted")
|
||||
else
|
||||
jarvis.log("warn", "focus.start: focus assist registry tweak failed")
|
||||
end
|
||||
|
||||
-- 3) Stretch reminder in 50 minutes (the canonical Pomodoro-XL value)
|
||||
local stretch_text = lang == "ru"
|
||||
and "Сэр, 50 минут истекли. Встаньте, разомнитесь, посмотрите вдаль."
|
||||
or "Sir, 50 minutes are up. Stand, stretch, look away from the screen."
|
||||
|
||||
local ok3, err3 = pcall(function()
|
||||
jarvis.scheduler.add({
|
||||
name = lang == "ru" and "Стретч-пауза" or "Stretch break",
|
||||
schedule = "in 50 minutes",
|
||||
action = { type = "speak", text = stretch_text },
|
||||
})
|
||||
end)
|
||||
if ok3 then
|
||||
table.insert(report, lang == "ru" and "пауза через 50 мин" or "break in 50 min")
|
||||
else
|
||||
jarvis.log("warn", "focus.start: scheduler.add failed: " .. tostring(err3))
|
||||
end
|
||||
|
||||
if #report == 0 then
|
||||
return jarvis.cmd.error(lang == "ru" and "Ничего не получилось включить."
|
||||
or "Couldn't enable anything.")
|
||||
end
|
||||
|
||||
local summary = table.concat(report, ", ")
|
||||
return jarvis.cmd.ok(lang == "ru"
|
||||
and ("Включил режим фокуса: " .. summary .. ". Удачной работы, сэр.")
|
||||
or ("Focus mode enabled: " .. summary .. ". Good luck, sir."))
|
||||
50
resources/commands/focus/stop.lua
Normal file
50
resources/commands/focus/stop.lua
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
-- Leave focus mode — undo the three side-effects of focus.start.
|
||||
|
||||
local lang = jarvis.context.language
|
||||
local report = {}
|
||||
|
||||
-- 1) Revert profile to default
|
||||
local ok1 = pcall(function() jarvis.profile.set("default") end)
|
||||
if ok1 then
|
||||
table.insert(report, lang == "ru" and "обычный профиль" or "default profile")
|
||||
end
|
||||
|
||||
-- 2) Re-enable notifications via the same registry key
|
||||
local ps = [[
|
||||
$key = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.QuietHours'
|
||||
if (Test-Path $key) {
|
||||
Set-ItemProperty -Path $key -Name 'NOC_GLOBAL_SETTING_TOASTS_ENABLED' -Value 1 -Type DWord
|
||||
}
|
||||
Write-Output 'fa-off'
|
||||
]]
|
||||
local cmd = 'powershell -NoProfile -ExecutionPolicy Bypass -Command "& {'
|
||||
.. ps:gsub('\r?\n', '; '):gsub('"', '\\"')
|
||||
.. '}"'
|
||||
local res = jarvis.system.exec(cmd)
|
||||
if res.success then
|
||||
table.insert(report, lang == "ru" and "уведомления включены" or "notifications restored")
|
||||
end
|
||||
|
||||
-- 3) Cancel any pending stretch reminders we created — match by name
|
||||
-- (scheduler has no native "tags" so we use the human name we set in start.lua)
|
||||
local cancelled = 0
|
||||
local target_names = { "Стретч-пауза", "Stretch break" }
|
||||
for _, task in ipairs(jarvis.scheduler.list()) do
|
||||
for _, name in ipairs(target_names) do
|
||||
if task.name == name then
|
||||
jarvis.scheduler.remove(task.id)
|
||||
cancelled = cancelled + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if cancelled > 0 then
|
||||
table.insert(report, string.format(lang == "ru"
|
||||
and "отменил %d напоминаний"
|
||||
or "cancelled %d reminders", cancelled))
|
||||
end
|
||||
|
||||
local summary = #report > 0 and table.concat(report, ", ")
|
||||
or (lang == "ru" and "ничего не было активно" or "nothing was active")
|
||||
return jarvis.cmd.ok(lang == "ru"
|
||||
and ("Фокус выключен: " .. summary .. ".")
|
||||
or ("Focus mode off: " .. summary .. "."))
|
||||
Loading…
Add table
Add a link
Reference in a new issue