feat: Wave 1 — 10 new packs (75 → 85 rust packs)
User picked from the fishki roadmap; this commit ships the 10 easy/medium
ones in one batch. No Rust core changes — all pure Lua + jarvis.* APIs.
Pack catalog
magic_8ball
- "ответь да или нет" / "магический шар" / "что скажешь"
- 15 канонических ответов, random pick. Pure fun.
github_issues (2 cmds)
- "какие issues" / "открытые issues" — gh issue list по сохранённому репо
- "мои issues" / "что мне назначено" — gh issue list --assignee @me
weather_extended (2 cmds, Open-Meteo, no key)
- "погода завтра" — temp min/max + conditions + rain note
- "прогноз на неделю" — общий диапазон температур
- Auto-detects location via ipinfo.io if not in memory; stores lat/lon/city.
rss_reader (3 cmds)
- "добавь rss <url>" — extracts URL, persists via memory под ключом "rss.<domain>"
- "что в ленте" — fetches first feed, parses <title> tags, speaks top 3
- "какие у меня rss" — lists subscribed feed domains
ics_event
- "добавь встречу завтра в 15:00 обсудить проект"
- Parses time (HH:MM или "в HH") + date keywords (сегодня/завтра/послезавтра)
- Writes valid iCalendar v2.0 file to ~/Documents/jarvis-events/
- jarvis.system.open → дефолтный handler (Outlook/Mail/whatever)
backup
- "сделай бекап" — PowerShell Compress-Archive всех state files из APPDATA/Jarvis
- Outputs to ~/Documents/jarvis-backup-<YYYYMMDD-HHMMSS>.zip
- Bundles: long_term_memory, schedule, macros, profiles/, active_profile, llm_backend, settings
clip_history (3 cmds, 20-slot rolling buffer)
- "запиши буфер" — push current clipboard onto memory keys clip.0..clip.19
- "что я копировал" — speak preview of last 3
- "верни первый/второй/третий буфер" — restore clip.N to clipboard
notif_queue (2 cmds)
- "что я пропустил" — enumerate memory keys "notif.*", speak last 5 by recency
- "очисти уведомления" — purge all notif.* keys
- Producers (scheduler/macros/llm) can later push to memory[notif.<ts>] = text
password_vault (3 cmds, Windows DPAPI)
- "сохрани пароль от GitHub" — encrypts current clipboard content via DPAPI
(CurrentUser scope), base64-stored in memory[vault.GitHub]. Clears clipboard.
Password is NEVER spoken or written to disk in plaintext.
- "пароль от GitHub" — decrypts via DPAPI, restores to clipboard for 30 sec,
schedules auto-clear via jarvis.scheduler. Speaks only "Пароль от X в буфере."
- "какие у меня пароли" — list of stored service names.
habit_streaks (2 cmds, integrates with habit_nudge)
- "сколько дней подряд" / "статистика привычек" — reads memory keys
"habit_streak.<habit>.<YYYY-MM-DD>", computes consecutive-day streak per habit.
- "я попил воды" / "отметь привычку" — marks today's check-in.
Maps voice to habit: воды→water, размял/зарядк→stretch, глаз→eyes.
Tests: 6 commands tests pass (auto-validate the 10 new packs).
This commit is contained in:
parent
4d3d664abd
commit
c4b22618f8
30 changed files with 1086 additions and 0 deletions
37
resources/commands/weather_extended/command.toml
Normal file
37
resources/commands/weather_extended/command.toml
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Extended weather forecast — Open-Meteo (free, no key).
|
||||
# Existing `weather/` pack covers "what's the weather now"; this adds forecast.
|
||||
|
||||
[[commands]]
|
||||
id = "weather.tomorrow"
|
||||
type = "lua"
|
||||
script = "tomorrow.lua"
|
||||
sandbox = "full"
|
||||
timeout = 15000
|
||||
|
||||
[commands.phrases]
|
||||
ru = [
|
||||
"погода завтра",
|
||||
"что с погодой завтра",
|
||||
"завтра будет тепло",
|
||||
"прогноз на завтра",
|
||||
]
|
||||
en = ["weather tomorrow", "forecast tomorrow"]
|
||||
ua = ["погода завтра"]
|
||||
|
||||
|
||||
[[commands]]
|
||||
id = "weather.week"
|
||||
type = "lua"
|
||||
script = "week.lua"
|
||||
sandbox = "full"
|
||||
timeout = 20000
|
||||
|
||||
[commands.phrases]
|
||||
ru = [
|
||||
"прогноз на неделю",
|
||||
"погода на неделю",
|
||||
"что с погодой на неделю",
|
||||
"недельный прогноз",
|
||||
]
|
||||
en = ["weather this week", "weekly forecast"]
|
||||
ua = ["прогноз на тиждень"]
|
||||
57
resources/commands/weather_extended/tomorrow.lua
Normal file
57
resources/commands/weather_extended/tomorrow.lua
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
-- Tomorrow's forecast for the saved or auto-detected location.
|
||||
-- City stored via memory key "weather.lat" + "weather.lon" + "weather.city",
|
||||
-- or auto-detected via ipinfo on first run.
|
||||
local lat = jarvis.memory.recall("weather.lat")
|
||||
local lon = jarvis.memory.recall("weather.lon")
|
||||
local city = jarvis.memory.recall("weather.city")
|
||||
|
||||
if not lat or not lon then
|
||||
-- Auto-detect via ipinfo.io (free, no key)
|
||||
local ip = jarvis.http.json("https://ipinfo.io/json")
|
||||
if not ip or not ip.loc then
|
||||
return jarvis.cmd.error("Не получилось узнать местоположение.")
|
||||
end
|
||||
lat, lon = ip.loc:match("^([^,]+),(.*)$")
|
||||
if not lat then
|
||||
return jarvis.cmd.error("Не получилось разобрать координаты.")
|
||||
end
|
||||
city = ip.city or "ваш город"
|
||||
jarvis.memory.remember("weather.lat", lat)
|
||||
jarvis.memory.remember("weather.lon", lon)
|
||||
jarvis.memory.remember("weather.city", city)
|
||||
end
|
||||
|
||||
local url = string.format(
|
||||
"https://api.open-meteo.com/v1/forecast?latitude=%s&longitude=%s&daily=temperature_2m_max,temperature_2m_min,precipitation_sum,weather_code&timezone=auto&forecast_days=2",
|
||||
lat, lon
|
||||
)
|
||||
local data = jarvis.http.json(url)
|
||||
if not data or not data.daily then
|
||||
return jarvis.cmd.error("Прогноз недоступен.")
|
||||
end
|
||||
|
||||
local d = data.daily
|
||||
-- day 2 = tomorrow (day 1 = today in the array)
|
||||
local tmax = (d.temperature_2m_max and d.temperature_2m_max[2]) or nil
|
||||
local tmin = (d.temperature_2m_min and d.temperature_2m_min[2]) or nil
|
||||
local rain = (d.precipitation_sum and d.precipitation_sum[2]) or 0
|
||||
local code = (d.weather_code and d.weather_code[2]) or 0
|
||||
|
||||
if not tmax then
|
||||
return jarvis.cmd.error("Прогноз неполный.")
|
||||
end
|
||||
|
||||
local condition = "переменно"
|
||||
if code == 0 then condition = "ясно"
|
||||
elseif code <= 3 then condition = "переменная облачность"
|
||||
elseif code >= 51 and code <= 67 then condition = "дождь"
|
||||
elseif code >= 71 and code <= 77 then condition = "снег"
|
||||
elseif code >= 95 then condition = "гроза"
|
||||
end
|
||||
|
||||
local line = string.format("В %s завтра %s. От %d до %d градусов.",
|
||||
city or "вашем городе", condition, math.floor(tmin + 0.5), math.floor(tmax + 0.5))
|
||||
if rain > 5 then
|
||||
line = line .. " Возможны осадки."
|
||||
end
|
||||
return jarvis.cmd.ok(line)
|
||||
42
resources/commands/weather_extended/week.lua
Normal file
42
resources/commands/weather_extended/week.lua
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
local lat = jarvis.memory.recall("weather.lat")
|
||||
local lon = jarvis.memory.recall("weather.lon")
|
||||
local city = jarvis.memory.recall("weather.city")
|
||||
|
||||
if not lat or not lon then
|
||||
local ip = jarvis.http.json("https://ipinfo.io/json")
|
||||
if not ip or not ip.loc then
|
||||
return jarvis.cmd.error("Не получилось узнать местоположение.")
|
||||
end
|
||||
lat, lon = ip.loc:match("^([^,]+),(.*)$")
|
||||
city = ip.city or "ваш город"
|
||||
jarvis.memory.remember("weather.lat", lat)
|
||||
jarvis.memory.remember("weather.lon", lon)
|
||||
jarvis.memory.remember("weather.city", city)
|
||||
end
|
||||
|
||||
local url = string.format(
|
||||
"https://api.open-meteo.com/v1/forecast?latitude=%s&longitude=%s&daily=temperature_2m_max,temperature_2m_min&timezone=auto&forecast_days=7",
|
||||
lat, lon
|
||||
)
|
||||
local data = jarvis.http.json(url)
|
||||
if not data or not data.daily or not data.daily.temperature_2m_max then
|
||||
return jarvis.cmd.error("Прогноз недоступен.")
|
||||
end
|
||||
|
||||
local maxes = data.daily.temperature_2m_max
|
||||
local mins = data.daily.temperature_2m_min
|
||||
|
||||
-- Find min and max of the week
|
||||
local week_max, week_min = -100, 100
|
||||
for i = 1, #maxes do
|
||||
if maxes[i] > week_max then week_max = maxes[i] end
|
||||
if mins[i] < week_min then week_min = mins[i] end
|
||||
end
|
||||
|
||||
local line = string.format("Неделя в %s: днём от %d до %d градусов, ночью до %d.",
|
||||
city or "вашем городе",
|
||||
math.floor(week_min + 0.5),
|
||||
math.floor(week_max + 0.5),
|
||||
math.floor(week_min + 0.5))
|
||||
|
||||
return jarvis.cmd.ok(line)
|
||||
Loading…
Add table
Add a link
Reference in a new issue