-- 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, " "))