J.A.R.V.I.S-rust/resources/commands/fun/ask.lua
Bossiara13 a16d2401e7 arch + features: Lua jarvis.speak() / jarvis.llm() API, /commands GUI page, games / mouse / random_choice packs
Architecture — DRY at the Lua API surface:

  lua/api/tts.rs (new): jarvis.speak(text, opts?). opts.lang = ISO
  two-letter code (default "ru"); auto-picks first installed voice
  matching the culture. opts.async = true|false (default true). The
  9 packs that previously inlined a 60-character PS-SAPI string for
  every spoken reply can now reduce to one line. Refactored fun/,
  dice/, clipboard_read/ as proof — fun/ask.lua went from 75 lines
  of HTTP+SAPI boilerplate to ~28 lines of intent code.

  lua/api/llm.rs (new): jarvis.llm(messages, opts?). messages is a
  list of {role, content} tables, opts.max_tokens / .temperature /
  .top_p. Returns the assistant string or nil. Gated by sandbox
  allows_http() (so Standard+ packs only). Internally uses the
  existing jarvis_core::llm::LlmClient::complete_with, no duplicated
  HTTP plumbing.

  llm/client.rs: split complete() into complete_with(messages,
  max_tokens, temperature, top_p) for the new caller; old complete()
  is now a thin wrapper at temp=0.7 top_p=1.0 for backward compat.

GUI — /commands page rewrite:

  Replaces the "Раздел в разработке" placeholder. Calls Tauri command
  get_commands_list (already existed in tauri_commands/commands.rs,
  was wired but unused). Renders a search-filterable card grid:
    - cmd id (monospace)
    - type badge with colour by kind (lua=blue, ahk=red, cli=grey,
      voice=green, terminate=red, stop_chaining=violet)
    - sandbox badge
    - description line (if non-empty)
    - all phrases for currentLanguage, fallback to en, fallback to
      first available; each phrase in a small inline pill
  Toolbar: text input with magnifier icon + reload button (↻).
  Counter line shows visible/total + "Скажи Джарвис + любую фразу"
  hint. Counts down as you type the filter.

New packs (3, total 33 → 36):

  games/ — launch_game / list_games. Reads or creates
  %USERPROFILE%\Documents\jarvis-games.json (the sample preloads dota,
  cs2, elden ring, witcher 3, factorio + minecraft launcher path +
  fortnite epic URI). Trigger-strip + fuzzy name/alias match, then
  launches via steam://rungameid/N (Steam), epic:// (Epic Games), or
  start "" "path" (anything else). list_games speaks the configured
  library.

  mouse/ — left/right/middle/double click + scroll up/down. Single
  dispatch.lua + _mouse_helper.ps1. PS P/Invokes user32!mouse_event
  with the right flag pair (LEFTDOWN+LEFTUP / etc.), 30ms gap, doubles
  do two LEFT cycles with a 50ms gap, wheel uses ±360 ticks.

  random_choice/ — "выбери из X или Y или Z". Strips the trigger,
  splits on " или " / " or " / ", " / " либо " / " чи ", math.random
  picks one, speaks "Я выбираю N".

cargo test commands::tests still 3/3. 36 packs verified via
jarvis-gui startup log.
2026-05-15 12:58:16 +03:00

39 lines
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 cmd_id = jarvis.context.command_id
local prompts = {
joke = lang == "ru"
and "Расскажи одну короткую шутку на русском, 1-3 предложения. Без вступления и без 'вот шутка'. Просто шутка."
or "Tell one short joke in 1-3 sentences. No preamble.",
fact = lang == "ru"
and "Расскажи один интересный, неочевидный факт по любой теме. 1-3 предложения. Без 'вот факт'."
or "Tell one surprising fact in 1-3 sentences. No preamble.",
quote = lang == "ru"
and "Дай вдохновляющую цитату известного человека и автора. Без 'вот цитата'. Формат: <цитата> — <автор>."
or "Give one inspiring quote with author. Format: <quote> — <author>.",
compliment = lang == "ru"
and "Сделай искренний короткий комплимент пользователю, как британский дворецкий Джарвис. 1-2 предложения, обращение «сэр»."
or "Compliment the user briefly, in JARVIS-the-butler tone.",
}
math.randomseed(os.time() + jarvis.context.time.second * 7919)
local reply = jarvis.llm(
{
{ role = "system", content = prompts[cmd_id] or prompts.joke },
{ role = "user", content = "seed " .. tostring(math.random(1, 9999)) },
},
{ max_tokens = 220, temperature = 1.0 }
)
if not reply or reply == "" then
jarvis.system.notify("Fun", lang == "ru" and "Не получилось" or "Failed")
jarvis.audio.play_error()
return { chain = false }
end
local titles = { joke = "Анекдот", fact = "Факт", quote = "Цитата", compliment = "Комплимент" }
jarvis.system.notify(titles[cmd_id] or "Fun", reply:sub(1, 240))
jarvis.speak(reply, { lang = lang })
jarvis.audio.play_ok()
return { chain = false }