J.A.R.V.I.S-rust/resources/commands/window_switch/switch.lua
Bossiara13 a7c002c9d4 arch + features: jarvis.text API + brightness/window_switch/spelling/network/summarize (41 packs)
Architecture — close the trigger-strip duplication:

  lua/api/text.rs (new):
  + jarvis.text.strip_trigger(phrase, triggers) — case-insensitive
    "longest trigger wins" stripping, returns trimmed remainder. The
    11 packs that previously inlined a `for _, t in ipairs(triggers) do
    string.find ... s == 1 then sub` loop can drop to one call.
    Demonstrated in spelling/, window_switch/, summarize/.
  + jarvis.text.contains_any(phrase, needles) — boolean check for any
    of N substrings, case-insensitive. Useful for keyword routing.

5 new portable Lua packs (sandbox=full). 36 → 41 total. cargo test
commands::tests still 3/3.

brightness/ — brightness_up / down / max / min. WMI WmiMonitorBrightness
(read CurrentBrightness) + WmiMonitorBrightnessMethods.WmiSetBrightness
(write). ±20% step for up/down; max=100, min=10. Desktop monitors that
don'\''t expose the WMI namespace get a friendly "не поддерживается"
toast instead of a silent failure.

window_switch/ — switch_to_window. Strip trigger ("переключись на" /
"switch to" / etc.), apply the same alias map as process_kill
(хром→chrome, телега→telegram, ...), then PowerShell finds processes
by name OR window-title substring sorted by StartTime desc and uses
(New-Object -ComObject WScript.Shell).AppActivate($pid) on the top
match. Speaks the window title that got focus.

spelling/ — spell_out. Strips "произнеси по буквам" / "spell out" /
etc., iterates `word:gmatch(".")`, joins letters with ". " so SAPI
gives each one a natural micro-pause. Uses jarvis.text.strip_trigger
+ jarvis.speak — 24 lines total.

network/ — open_wifi_settings (ms-settings:network-wifi) +
open_bluetooth_settings (ms-settings:bluetooth) + my_ip. my_ip pulls
the first non-loopback, non-APIPA IPv4 with Get-NetIPAddress and
fetches WAN IP from api.ipify.org (5s timeout); speaks "Локальный X.
Внешний Y".

summarize/ — summarize_selection. Synthesises Ctrl+C through user32!
keybd_event (so the focused window copies its selection), waits
220 ms for the clipboard to populate, reads via
jarvis.system.clipboard.get(), bails if < 20 chars, truncates at
8000, sends to Groq @ temp 0.3 with a "3-5 sentences, keep names"
prompt, drops the summary back into the clipboard and speaks it.
Lets you select ANY text in ANY app (browser, PDF, IDE) and say
"суммируй" to get a spoken TL;DR.

The new packs explicitly use the new jarvis.text + jarvis.llm +
jarvis.speak API surface — no inline PS-SAPI boilerplate, no inline
Groq plumbing. Code is now intent-first.
2026-05-15 13:11:18 +03:00

51 lines
2.2 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local lang = jarvis.context.language
local triggers = {
"переключись на", "переключи на", "активируй окно", "покажи окно", "перейди в",
"switch to", "activate window", "focus window",
"перемкни на", "активуй вікно",
}
local query = jarvis.text.strip_trigger(jarvis.context.phrase or "", triggers):lower()
if query == "" then
jarvis.system.notify("Switch", lang == "ru" and "Какое окно?" or "Which window?")
jarvis.audio.play_error()
return { chain = false }
end
local aliases = {
["хром"] = "chrome", ["хрома"] = "chrome",
["едж"] = "msedge", ["эдж"] = "msedge",
["файрфокс"] = "firefox", ["фаерфокс"] = "firefox",
["вскод"] = "code", ["vs code"] = "code",
["дискорд"] = "discord",
["телега"] = "telegram", ["телеграм"] = "telegram",
["стим"] = "steam",
["обс"] = "obs64",
["проводник"] = "explorer",
["блокнот"] = "notepad",
["терминал"] = "windowsterminal",
["спотифай"] = "spotify",
["яндекс"] = "browser",
["браузер"] = "browser",
}
local target = aliases[query] or query
local ps = string.format([[
$procs = Get-Process | Where-Object { $_.MainWindowTitle -and ($_.ProcessName -like '*%s*' -or $_.MainWindowTitle -like '*%s*') } | Sort-Object -Property StartTime -Descending
if ($procs.Count -eq 0) { Write-Output 'NOT_FOUND'; exit 0 }
$p = $procs[0]
$wsh = New-Object -ComObject WScript.Shell
$null = $wsh.AppActivate($p.Id)
Write-Output $p.MainWindowTitle
]], target:gsub("'", ""), target:gsub("'", ""))
local res = jarvis.system.exec(string.format('powershell -NoProfile -Command "%s"', ps:gsub('"', '\\"')))
local out = (res.stdout or ""):gsub("[\r\n]+$", ""):gsub("^%s+", "")
if out == "NOT_FOUND" or out == "" then
jarvis.system.notify("Switch", (lang == "ru" and "Не нашёл: " or "Not found: ") .. query)
jarvis.audio.play_not_found()
else
jarvis.system.notify(lang == "ru" and "Переключаюсь" or "Switching", out:sub(1, 80))
jarvis.audio.play_ok()
end
return { chain = false }