New `wave59_handlers.py` (~250 lines) mirroring four Rust-only packs:
- wol: pure-Python magic packet via socket + SO_BROADCAST. No PowerShell
shellout (unlike the Rust pack). Reads MAC from memory_store under
'wol_<alias>' or JARVIS_WOL_TARGET env. Same MAC format tolerance
(colons / dashes / dots / bare) as the Rust normaliser.
- banter: pause/resume state + fire-one. Python edition doesn't run a
background banter thread (the Rust daemon already does), so this is
just the user-facing surface — same voice phrases work.
- conversation: do_conversation_summary calls Groq with last 12 turns
from main.py's `message_log`. set_history_ref() injects the live list
reference at startup so the handler reads up-to-date history without
a circular import. Offline-safe: GROQ_TOKEN missing → speak the last
user message instead. do_conversation_repeat re-speaks the last
assistant turn.
- ddg_answer: urllib + DuckDuckGo Instant Answer JSON. Picks
AbstractText → Answer → Definition → RelatedTopics[0]. Opens
duckduckgo.com search fallback when nothing instant.
extensions.py / main.py / commands.yaml: 7 new dispatch entries +
proxy fns. commands.yaml now at 207 entries.
tests/test_wave59_handlers.py: 11 unit tests for MAC normalisation,
magic packet shape, WOL error paths, banter state machine, DDG trigger
stripping, conversation history handling. Network calls deliberately
NOT exercised here — they belong to integration tests.
Tests: 104 → 115 (+11).
New module `wave68_handlers.py` (~270 lines) covering the Rust packs that
were Rust-only after Waves 6-8:
- memory_admin: do_memory_count/list/wipe (with full RU plural decl.)
- cooking: do_cooking + reusable match_recipe(phrase) for the 15-dish
preset table. Schedules a "ready!" reminder via scheduler_store.
- leftoff: do_leftoff stitches memory + scheduled tasks + last reply
into a one-paragraph recap. Offline.
- trivia: do_trivia random one-liner from RU/EN MCU pools.
- routines: do_good_night (sleep profile + cancel one-shots),
do_good_morning (default profile + agenda hint),
do_coffee_break (5-min check-in via scheduler).
memory_store: new clear_all() returning removed count, atomic via _save.
extensions.py: imports + set_speak wiring + 9 proxy do_* fns.
main.py: 9 new dispatch elifs.
commands.yaml: 9 new entries (now 196 total).
tests/test_wave68_handlers.py: 15 unit tests covering each handler.
Test helper `_rewire()` re-imports state modules via the existing
isolated_state fixture then re-binds the wave68_handlers module-level
refs — fixes the gotcha where module-level imports cache the OLD
memory_store / scheduler_store instances from process startup.
Tests: 81 → 96 (+15).
Outlook COM (`outlook_handlers.py`, agent):
- 4 handlers mirroring Rust pack: unread_count, latest, send_clipboard,
summarize_inbox. Uses `win32com.client` with lazy import so the module
loads even when pywin32 is missing — handlers degrade gracefully and
speak a "Outlook недоступен" reply.
- `requirements.txt`: pywin32>=305 (optional).
- 7 unit tests mock `_outlook_session` via unittest.mock.
Time tracker (`time_tracker_handlers.py`, agent):
- 5 handlers: start, stop, today, week, reset. JSON store at
`<here>/time_tracker.json`, atomic write-then-rename.
- Same shape as the Rust pack's `jarvis.state` blob: current_session_start
+ sessions[{start,end}]. Local-calendar today boundary.
- Full Russian pluralisation (час/часа/часов, минута/минуты/минут).
- 14 unit tests using the existing `isolated_state` fixture in conftest.py.
`extensions.py` + `main.py`: imports + 9 new proxy do_* functions + 9
new dispatch elifs. `commands.yaml`: 9 new entries.
Tests: 60 → 81 (+14 tracker + 7 outlook).
Python parity for the 5 personality voice commands shipped on the
Rust side:
- New `personality_handlers.py` (~150 lines): do_personality_{greet,
thanks, compliment, how_are_you, tony_quote}. Each picks one of
7-10 phrases per language (RU/EN) at random; greet additionally
buckets by time-of-day (morning/midday/evening/night).
- `extensions.py`: imports + 5 proxy `do_personality_*` functions
pointing at the new module, plus set_speak wiring so handlers can
TTS via the runtime's voice.
- `main.py`: 5 new dispatch elifs feeding the new action types.
- `commands.yaml`: 5 new entries (`personality_*`) mapping voice
phrases to action types.
- `tests/test_personality_handlers.py`: 6 unit tests confirming
each handler returns a non-empty string from the expected pool.
- `.gitignore`: stop tracking runtime state generated by tests
(profiles/, long_term_memory.json, schedule.json, macros.json,
llm_backend.txt, llm_history.json) — these are user data, not
source.
Tests: 54 → 60 (+6).
Plugin loader (mirrors Rust #29):
- plugins_store.py walks %APPDATA%\com.priler.jarvis\plugins\<name>\
for commands.yaml fragments and merges them into VA_CMD_LIST at
startup. Same schema as the project root commands.yaml. Per-pack
`disabled` flag file skips a pack without deletion. Built-in ids
win conflicts so a malicious pack can't silently override
open_browser. 9 unit tests (parity with the Rust tests).
- main.py: plugin merge runs after the root yaml load; logs the
number of extra commands picked up.
Flet GUI (#27 — first parity with the Rust Tauri GUI):
- New gui/ package: __main__.py launches via `python -m gui` (or
gui.bat). app.py routes between 7 pages (Главная / Команды /
Макросы / Расписание / Память / Плагины / Настройки) via
NavigationRail; dark theme matching the Tauri look.
- gui/services.py centralises every store-module call the pages
share — single place to swap implementations later.
- One file per page in gui/pages/, all expose `build(page)` and use
the same card layout idiom. Pages mirror the Tauri ones feature-
for-feature: home (status + counters + launcher), commands
(filterable list of all VA_CMD_LIST entries), macros (list +
delete + recording banner), scheduler (list + remove), memory
(add/forget/search), plugins (toggle/open folder), settings
(profile + LLM hot-swap).
- requirements.txt: flet>=0.85 (optional; assistant runs without).
- 3 smoke tests verify imports + build callables; skip cleanly when
Flet isn't installed.
README: documents both the GUI and the plugin layout in user-facing
terms. Tests: 42 → 54 (+9 plugins +3 GUI smoke).