80 lines
3.2 KiB
Lua
80 lines
3.2 KiB
Lua
|
|
-- Summarize the last few unread emails into one paragraph via the LLM.
|
||
|
|
-- Pulls FROM+SUBJECT of up to 5 unread items, then asks the model for a
|
||
|
|
-- short paragraph in the user's language.
|
||
|
|
|
||
|
|
local lang = jarvis.context.language
|
||
|
|
local helper = jarvis.context.command_path .. "\\_outlook.ps1"
|
||
|
|
local cmd = string.format(
|
||
|
|
'powershell -NoProfile -ExecutionPolicy Bypass -File "%s" -Action summarize_inbox -Limit 5',
|
||
|
|
helper
|
||
|
|
)
|
||
|
|
|
||
|
|
local res = jarvis.system.exec(cmd)
|
||
|
|
local out = (res.stdout or ""):gsub("\r", "")
|
||
|
|
|
||
|
|
if not res.success or out == "" then
|
||
|
|
jarvis.log("error", "outlook summarize_inbox exec failed: " .. tostring(res.stderr))
|
||
|
|
return jarvis.cmd.error(lang == "ru"
|
||
|
|
and "Outlook недоступен — запусти Outlook сначала."
|
||
|
|
or "Outlook is unavailable — start Outlook first.")
|
||
|
|
end
|
||
|
|
|
||
|
|
local lines = {}
|
||
|
|
for line in out:gmatch("[^\n]+") do table.insert(lines, line) end
|
||
|
|
|
||
|
|
local status = lines[1] or ""
|
||
|
|
if status:sub(1, 3) == "ERR" then
|
||
|
|
jarvis.log("warn", "outlook summarize_inbox: " .. status)
|
||
|
|
return jarvis.cmd.error(lang == "ru"
|
||
|
|
and "Outlook недоступен — запусти Outlook сначала."
|
||
|
|
or "Outlook is unavailable — start Outlook first.")
|
||
|
|
end
|
||
|
|
|
||
|
|
local emails = {}
|
||
|
|
for i = 2, #lines do
|
||
|
|
local from, subject = lines[i]:match("^FROM\t(.-)\tSUBJECT\t(.*)$")
|
||
|
|
if from then
|
||
|
|
table.insert(emails, { from = from, subject = subject or "" })
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if #emails == 0 then
|
||
|
|
return jarvis.cmd.not_found(lang == "ru"
|
||
|
|
and "Непрочитанных писем нет."
|
||
|
|
or "No unread emails.")
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Build the prompt
|
||
|
|
local list_str = ""
|
||
|
|
for i, m in ipairs(emails) do
|
||
|
|
list_str = list_str .. string.format("%d. From: %s | Subject: %s\n", i, m.from, m.subject)
|
||
|
|
end
|
||
|
|
|
||
|
|
local sys_prompt = lang == "ru"
|
||
|
|
and "Ты помощник по почте. Кратко опиши, что лежит в инбоксе, ОДНИМ абзацем (2-4 предложения). Сгруппируй по темам/отправителям если возможно. Без преамбулы, без перечисления списком."
|
||
|
|
or "You are an email assistant. Briefly describe the inbox in ONE paragraph (2-4 sentences). Group by topic/sender when possible. No preamble, no bullet list."
|
||
|
|
|
||
|
|
local user_prompt = (lang == "ru" and "Непрочитанные письма:\n" or "Unread emails:\n") .. list_str
|
||
|
|
|
||
|
|
local reply = jarvis.llm(
|
||
|
|
{ { role = "system", content = sys_prompt },
|
||
|
|
{ role = "user", content = user_prompt } },
|
||
|
|
{ max_tokens = 250, temperature = 0.4 }
|
||
|
|
)
|
||
|
|
|
||
|
|
if not reply or reply == "" then
|
||
|
|
-- Fallback: simple flat enumeration when LLM is unavailable.
|
||
|
|
local parts = {}
|
||
|
|
for _, m in ipairs(emails) do
|
||
|
|
table.insert(parts, string.format("%s — %s", m.from, m.subject))
|
||
|
|
end
|
||
|
|
local fallback = (lang == "ru"
|
||
|
|
and string.format("Непрочитанных: %d. ", #emails)
|
||
|
|
or string.format("Unread: %d. ", #emails)) .. table.concat(parts, "; ") .. "."
|
||
|
|
jarvis.system.notify(lang == "ru" and "Инбокс" or "Inbox", fallback)
|
||
|
|
return jarvis.cmd.ok(fallback)
|
||
|
|
end
|
||
|
|
|
||
|
|
jarvis.system.notify(lang == "ru" and "Инбокс" or "Inbox", reply)
|
||
|
|
return jarvis.cmd.ok(reply)
|