feat(commands): tier-1 PC tools — window mgmt, clipboard, notes, process killer, web search

Five new portable Lua command packs. Bumps the total from 11 to 16 packs.
All sandbox=full, all dispatched via jarvis.system.exec or jarvis.fs / jarvis.system
APIs, no new Rust code, post_build.py --sync copies them under target/.
cargo test -p jarvis-core --lib commands::tests passes 3/3 against all 16.

window/ — 8 commands, single dispatch.lua keyed by jarvis.context.command_id:
  show_desktop / maximize_window / minimize_window / snap_left / snap_right
  / close_window / restore_all / task_view. _window_helper.ps1 P/Invokes
  user32!keybd_event for arbitrary combos like "win+d", "alt+f4",
  "win+shift+m". Uses one shared script per pack — much less duplication
  than the volume/ approach.

clipboard_read/ — read_clipboard. Pulls jarvis.system.clipboard.get(),
caps preview at 400 chars, then shells PowerShell System.Speech to actually
speak it aloud (auto-picks the first ru-RU voice if present). Also fires a
notify with a 120-char snippet.

notes/ — add_note + open_notes. add_note strips the trigger phrase from
the recognized voice, appends "[YYYY-MM-DD HH:MM] body\n" to
%USERPROFILE%\Documents\jarvis-notes.txt via jarvis.fs.append (creates
the file on first call). open_notes opens the file in the default editor
via jarvis.system.open. Trigger list covers RU/EN/UA variants of
"запиши" / "запомни" / "write down" / etc.

process_kill/ — kill_process. Trigger-strips "закрой программу" / "убей
процесс" / etc., then runs the remainder through an alias map (хром→
chrome, телега→telegram, спотифай→spotify, edge/edge/едж→msedge etc.,
20+ entries) before invoking taskkill /F /IM. Notifies success/not-found.

websearch/ — search_google / search_youtube / search_wiki / search_yandex.
Single dispatch.lua reads jarvis.context.command_id to pick the base URL,
URL-encodes the query (Lua %02X gsub, not relying on jarvis.http), opens
the resulting link via jarvis.system.open (system default browser).

Portability check: every helper resolves paths via $env:USERPROFILE /
jarvis.context.command_path / jarvis.system.env — no hardcoded C:\ refs.
This commit is contained in:
Bossiara13 2026-05-15 11:27:02 +03:00
parent 3d127f05c0
commit 16ef413962
12 changed files with 545 additions and 0 deletions

View file

@ -0,0 +1,56 @@
local lang = jarvis.context.language
local phrase = (jarvis.context.phrase or ""):lower()
local triggers = {
"запиши заметку", "запиши идею", "сделай заметку", "запомни идею",
"запиши", "запомни",
"write down", "take a note", "remember this", "note down",
"запиши ідею", "зроби нотатку",
}
local body = phrase
for _, t in ipairs(triggers) do
local s, e = string.find(body, t, 1, true)
if s == 1 then
body = body:sub(e + 1)
break
end
end
body = body:gsub("^[%s,:%.]+", ""):gsub("%s+$", "")
if body == "" then
jarvis.system.notify(
lang == "ru" and "Заметка" or "Note",
lang == "ru" and "Что записать?" or "What to write?"
)
jarvis.audio.play_error()
return { chain = false }
end
local userprofile = jarvis.system.env("USERPROFILE") or "C:\\Users\\Public"
local notes_path = userprofile .. "\\Documents\\jarvis-notes.txt"
local t = jarvis.context.time
local stamp = string.format("%s-%s-%s %s:%s",
t.year, t.month, t.day, t.hour, t.minute)
local line = string.format("[%s] %s\n", stamp, body)
local ok, err = pcall(function()
jarvis.fs.append(notes_path, line)
end)
if not ok then
jarvis.log("error", "notes append failed: " .. tostring(err))
jarvis.system.notify("Заметка", lang == "ru" and "Не удалось записать" or "Append failed")
jarvis.audio.play_error()
return { chain = false }
end
jarvis.log("info", "note appended: " .. body)
jarvis.system.notify(
lang == "ru" and "Заметка записана" or "Note saved",
body:sub(1, 120)
)
jarvis.audio.play_ok()
return { chain = false }

View file

@ -0,0 +1,24 @@
[[commands]]
id = "add_note"
type = "lua"
script = "add.lua"
sandbox = "full"
timeout = 5000
[commands.phrases]
ru = ["запиши", "запиши заметку", "запиши идею", "запомни", "запомни идею", "сделай заметку"]
en = ["write down", "take a note", "remember this", "note down"]
ua = ["запиши", "запиши ідею", "зроби нотатку"]
[[commands]]
id = "open_notes"
type = "lua"
script = "open.lua"
sandbox = "full"
timeout = 3000
[commands.phrases]
ru = ["покажи заметки", "открой заметки", "что я записал"]
en = ["show notes", "open notes"]
ua = ["покажи нотатки", "відкрий нотатки"]

View file

@ -0,0 +1,16 @@
local lang = jarvis.context.language
local userprofile = jarvis.system.env("USERPROFILE") or "C:\\Users\\Public"
local notes_path = userprofile .. "\\Documents\\jarvis-notes.txt"
if not jarvis.fs.exists(notes_path) then
jarvis.system.notify(
lang == "ru" and "Заметки" or "Notes",
lang == "ru" and "Файл пуст или не создан" or "No notes yet"
)
jarvis.audio.play_not_found()
return { chain = false }
end
jarvis.system.open(notes_path)
jarvis.audio.play_ok()
return { chain = false }