feat: Wave 7 — 'where did I leave off' + Stark trivia
Some checks are pending
Rust CI / cargo test (jarvis-core) (push) Waiting to run
Rust CI / cargo clippy (push) Waiting to run
Rust CI / cargo check (workspace) (push) Waiting to run

leftoff/recap.lua:
- Voice "на чём я остановился" / "where did I leave off" stitches a
  one-paragraph recap from four independent sources:
    1. last assistant LLM reply (jarvis.llm_last_reply)
    2. 3 most-recent memory facts (sorted by last_used_at)
    3. count + name of the next scheduled task
    4. active profile (implicit, in tone)
- Fully offline — no LLM call, just pulls from local state.

trivia/trivia.lua:
- 15 RU + 15 EN one-liners about the Stark universe (suits, arc reactor,
  in-universe trivia about J.A.R.V.I.S. itself). Doesn't overlap with
  the verbatim quote pool in personality/tony_quote.lua.

Pack count: 95 → 97. Tests: 140 still pass.
This commit is contained in:
Bossiara13 2026-05-16 14:41:56 +03:00
parent 8f46bd735a
commit 7e1d1c3cc7
4 changed files with 162 additions and 0 deletions

View file

@ -0,0 +1,27 @@
# "Where did I leave off" — pull recent context from across the assistant's
# state (last conversation, latest memory facts, last tracker session, latest
# scheduled task) and read out a one-paragraph recap. Nice for picking up after
# a coffee break or returning to the PC.
[[commands]]
id = "leftoff.recap"
type = "lua"
script = "recap.lua"
sandbox = "full"
timeout = 8000
[commands.phrases]
ru = [
"на чём я остановился",
"на чем я остановился",
"напомни что делал",
"что я делал",
"где я остановился",
"продолжи откуда я",
]
en = [
"where did i leave off",
"what was i doing",
"recap my session",
"remind me what i was doing",
]

View file

@ -0,0 +1,62 @@
-- Read out a short recap of the user's recent activity. Pulls from four
-- independent sources, picks the freshest, and stitches them into a one-shot
-- TTS reply. Works fully offline — no LLM call.
--
-- Sources:
-- 1. Last assistant reply (jarvis.llm_last_reply)
-- 2. 3 most recent memory facts (sorted by last_used_at desc)
-- 3. Active scheduled tasks (jarvis.scheduler.list)
-- 4. Active profile (just to colour the tone)
local lang = jarvis.context.language
local parts = {}
-- 1) Recent memory facts (last_used_at desc, top 3)
local facts = jarvis.memory.all() or {}
if #facts > 0 then
table.sort(facts, function(a, b)
return (a.last_used_at or 0) > (b.last_used_at or 0)
end)
local items = {}
for i = 1, math.min(3, #facts) do
local v = (facts[i].value or ""):sub(1, 50)
table.insert(items, facts[i].key .. "" .. v)
end
if lang == "ru" then
table.insert(parts, "Из памяти: " .. table.concat(items, "; ") .. ".")
else
table.insert(parts, "From memory: " .. table.concat(items, "; ") .. ".")
end
end
-- 2) Upcoming scheduled tasks (just count + the next one)
local tasks = jarvis.scheduler.list() or {}
if #tasks > 0 then
-- Tasks have no "next_fire" exposed at Lua-level, so just count + name first.
local first_name = tasks[1].name or "task"
if lang == "ru" then
table.insert(parts, "В расписании " .. tostring(#tasks) .. ", ближайшее: " .. first_name .. ".")
else
table.insert(parts, tostring(#tasks) .. " scheduled, next: " .. first_name .. ".")
end
end
-- 3) Last assistant reply (if any)
local last = jarvis.llm_last_reply()
if last and last ~= "" then
-- Trim to ~100 chars to keep the recap snappy
local snippet = last:gsub("%s+", " "):sub(1, 120)
if lang == "ru" then
table.insert(parts, "Я говорил: " .. snippet)
else
table.insert(parts, "I said: " .. snippet)
end
end
if #parts == 0 then
return jarvis.cmd.not_found(lang == "ru"
and "Ничего недавно не происходило, сэр."
or "Nothing recent to recap, sir.")
end
return jarvis.cmd.ok(table.concat(parts, " "))

View file

@ -0,0 +1,27 @@
# Random MCU / Iron Man trivia — one of dozens of fixed lines per language.
# Different from the existing `interesting_fact/` (which is general curiosity)
# and `personality/tony_quote` (which is verbatim film quotes).
# These are short factoids about the suit, the Stark universe, etc.
[[commands]]
id = "trivia.iron_man"
type = "lua"
script = "trivia.lua"
sandbox = "minimal"
timeout = 2000
[commands.phrases]
ru = [
"расскажи про железного человека",
"факт про железного человека",
"trivia про старка",
"интересное про старка",
"марвел факт",
]
en = [
"tell me about iron man",
"iron man trivia",
"stark trivia",
"marvel fact",
"tell me a marvel fact",
]

View file

@ -0,0 +1,46 @@
-- Random one-liner about the Stark universe. Pool is hand-curated so it
-- doesn't repeat what `personality/tony_quote` already does (verbatim quotes)
-- and stays in the realm of in-universe trivia rather than out-of-universe
-- production facts.
local lang = jarvis.context.language
local pool_ru = {
"Первый костюм Старк собрал в пещере в Афганистане из подручного железа. Десять рабочих недель, ноль вентиляции.",
"Дуговый реактор изначально питал электромагнит, удерживающий осколки шрапнели у самого сердца.",
"Палладий в первом реакторе медленно отравлял Старка. Решением стал новый, синтезированный отцом, элемент.",
"Mark I весил около 200 килограммов и летал лишь однажды — на побег из плена.",
"Mark II был первым серебристым прототипом. Старк сам же его и потерял — у Колонеля Роудса.",
"Mark III выкрашен в красно-золотой потому, что чистое золото оказалось мягче, чем хотелось.",
"Mark V — складной костюм в чемодане. Идеальное оружие на званый ужин.",
"Hulkbuster (Mark XLIV) был запущен совместно с Брюсом Беннером — на случай, если Халк выйдет из берегов.",
"Mark XLII собирался к носителю по запросу — ранние тесты заканчивались переломами.",
"Я, Сэр, появился в фильме «Железный человек» 2008 года. Меня озвучил Пол Беттани.",
"Имя J.A.R.V.I.S. — отсылка к Эдвину Джарвису, дворецкому отца Тони, Говарда Старка.",
"После событий «Эры Альтрона» программа J.A.R.V.I.S. была интегрирована в Vision. Это уже другая история.",
"Шрапнель, прижатая электромагнитом — это вольная экстраполяция комиксов. В книге Тони просто носил жилет.",
"Реактор-дуга в груди не лишал Старка возможности проходить через металлодетекторы. Не каждый раз.",
"F.R.I.D.A.Y. пришла мне на смену в «Эре Альтрона». Не самая лестная замена, но что поделать.",
}
local pool_en = {
"Stark built the first suit in a cave in Afghanistan from scavenged parts. Ten weeks, no ventilation.",
"The arc reactor originally powered an electromagnet keeping shrapnel away from his heart.",
"Palladium in the first reactor was slowly poisoning him. The cure was a new element his father had synthesised.",
"Mark I weighed roughly 200 kilograms and flew exactly once — for the escape.",
"Mark II was the first silver prototype. Stark himself lost it — to Colonel Rhodes.",
"Mark III is red-and-gold because pure gold turned out to be too soft.",
"Mark V folds into a briefcase. Useful at galas.",
"Hulkbuster — Mark XLIV — was built with Bruce Banner, just in case.",
"Mark XLII assembled around its wearer on demand. Early tests broke bones.",
"I, sir, first appeared in Iron Man (2008). Paul Bettany voiced me.",
"The name J.A.R.V.I.S. nods to Edwin Jarvis, butler to Tony's father Howard.",
"After Age of Ultron, my code was folded into Vision. A different story.",
"Shrapnel held back by an electromagnet is a film conceit; the comics had Tony in a chest plate.",
"An arc reactor doesn't always trigger a metal detector. Not always.",
"F.R.I.D.A.Y. replaced me in Age of Ultron. Not a flattering swap.",
}
local pool = (lang == "ru") and pool_ru or pool_en
local idx = math.random(#pool)
return jarvis.cmd.ok(pool[idx])