Releases: Luna-coreX/RinaAssistant
Release list
RinaAssistant v3.1.0 — Fix & Security
3.1.0 — 2026-09-01
An intermediate release between 3.0.0 and the 4.0.0 split. It adds one new behaviour — the application now keeps a log — and otherwise closes findings from two audits, mine and an external review, preparing the ground for moving the core into its own process.
Highlights
- Logs. Levels, rotation, and a separate security log. Message texts are never written unless you explicitly ask for them.
- No shell, no bare names. The last
shell=Trueis gone; programs are launched by absolute path. - Speech no longer overlaps itself. One playback queue, one temporary file per answer.
- Commands left the interface thread. Typing a command no longer freezes the window while the model thinks.
- Nothing gets stuck. Test buttons, recognition failures and the command pipeline report what happened instead of going quiet.
Observability
Logging with levels. New core/logging_setup.py — DEBUG / INFO / WARNING / ERROR, rotating files (1 MB × 3) under %APPDATA%/RinaAssistant/logs/, level selectable in Settings → Diagnostics. Uncaught exceptions are recorded, including those in background threads — which previously killed the thread in silence and left the user looking at an action that simply never happened.
Message texts stay private. Only their length is logged unless "Log message texts" is deliberately switched on, so a log can be attached to a bug report without disclosing conversations. When the setting is on, the log says so on its first line.
A separate security log. security.log records what both audits had to reconstruct by hand: plugin installs and replacements, rejected plugin names, command imports (how many accepted, how many discarded), execution of power actions, requests to a non-local model address, and refusal of a dangerous action at the confirmation prompt.
Security
The last shell=True is gone. It lived in voice/commands.py, launching discord, calc, notepad, explorer and start chrome by bare name through the command interpreter. No user input reached it, so this was not command injection — but Windows searches the current directory, so a file placed next to the application would have run instead. Programs are now resolved to an absolute path (System32 → %SystemRoot% → PATH) and started without a shell. Verified by planting a decoy notepad.exe in the working directory: the real one still wins.
The browser fallback works again. start chrome could not survive removing the shell; if Chrome is not found, the default browser opens instead of nothing happening.
Store apps report honestly. Launching a UWP app always returned success, because explorer.exe says nothing about what became of shell:AppsFolder\<id> — and waiting for it is unsafe, since it becomes the desktop shell process when not already running. The identifier is now checked against the index before launching, and an unknown one fails without spawning anything.
A vanished program says so. Command targets and index entries are checked for existence before launching, and the answer names the cause — "Не нашла «foo.exe» — программу удалили или перенесли" — instead of "Не получилось выполнить команду". Bare names such as discord are deliberately left alone: Windows resolves them through the App Paths registry, and that is a legitimate way to write a command.
SECURITY.md. Private reporting through GitHub Security Advisories, plus an explicit description of the trust boundaries — most importantly that a plugin is ordinary Python with the application's rights, and there is no sandbox. Installing one is as consequential as running a downloaded program.
Reliability
Speech no longer overlaps itself. Playback went through no queue and three fixed temporary filenames (rina_gtts.mp3, rina_edge.mp3, rina_piper.wav), so two answers in quick succession overwrote each other's file and played at the same time. There is now a single playback worker, one uniquely named file per synthesis, deletion after playback, and a failed file no longer kills the worker.
The microphone no longer hears Rina. _speaking was one flag for the whole core, so with two overlapping answers the first to finish cleared it and the microphone opened under speech that was still playing. It is now a counter: the flag holds until the last speaker finishes.
Default settings are copied properly. dict(DEFAULTS) is a shallow copy, and more than a dozen defaults are mutable — plugin_settings, wake_words, action_hotkeys, app_aliases, program_folders, custom_commands. Changing a plugin setting wrote into the module-level defaults, so "reset" restored the already-modified value rather than the factory one.
Stores no longer lose writes. History, reminders, usage statistics and user commands all used read-modify-write: two threads read the same state and the second overwrote the first. All of them now run under one store-wide lock. Under load — four threads writing at once — 160 of 160 history entries, 60 of 60 reminders, and exactly 200 of 200 counter increments survive.
Test buttons come back. MicTester._worker had no try/finally: an exception left the button greyed out until restart. The model's "Check connection" button had the same shape, and http.client.HTTPException — which does not inherit from OSError — escaped the request handler entirely. Both now report the cause and return to a usable state.
Recognition failures are visible. _listen_worker had a finally but no except, so a failing engine cleared the indicator and killed the thread without a word.
Responsiveness
Commands run off the interface thread. Typed commands drove the entire pipeline in the GUI thread; with the language model enabled, that is several seconds of a frozen window. Commands now go through a single queue inside the core — the window stays live, ordering is preserved, and an exception in one command no longer strands every command behind it. Always-listen still waits for completion, because it must not listen while Rina is answering.
Hotkeys fire once. Holding a combination produces key auto-repeat, and every repeat was reported as a fresh activation. A 300 ms suppression window per combination fixes it.
Theme switching is safe. Pages were destroyed from inside the theme-change signal handler — while that signal was still being delivered to those same pages. The rebuild is now deferred to the next event-loop turn and guarded against re-entry. The tray menu is rebuilt on theme and language change instead of keeping the old palette and the old language, and its old actions are released rather than accumulated.
Plugins load after Qt exists. plugin_manager.discover() ran before QApplication was constructed. It only reads manifests today, but it also loads the code of enabled plugins — and a plugin touching Qt at that moment would have crashed the launch with nothing to tell the user.
Parsing
Compound durations. "Поставь таймер на 1 час 30 минут" was read as one hour, and the user found out ninety minutes later. All number-unit pairs are now summed: 5400 seconds for that phrase, 8130 for "2 часа 15 минут 30 секунд".
Percentages only when asked. Percentage parsing ran before the check that the phrase was addressed to the calculator at all, so ordinary speech containing "20 процентов от 3000" was answered with arithmetic. It now follows the same admission rule as the rest of the calculator: an explicit trigger, or a phrase that is nothing but the expression.
Decisions
Plugin trust boundary (ADR). Recorded for 4.0.0 as 4.0-H07: a plugin gets its own process and speaks to the core over the same protocol as the shell. It lands there rather than in 5.0.0 because H03 rewrites the Plugin API from scratch anyway, D02 designs the protocol anyway, and C04 builds the permission catalogue anyway — so a plugin becomes one more protocol client instead of a separate mechanism. Deferring would mean changing the Plugin API twice and migrating the bundled plugins twice. A full sandbox with resource limits was rejected as a separate research task: in-process sandboxing does not exist in Python, and OS-level limits can be layered on top of H07 later if needed.
Deliberately not done
- Moving all storage to SQLite, as the external review proposed. 5.0.0 introduces SQLite for memory and 4.0.0 migrates user data; doing that migration twice buys nothing. The races are fixed with a lock instead.
- An allow-list of directories for command targets. It would break portable programs, which is the case the mechanism was built for. Imported commands remain sanitised and disabled.
- Schema validation of event payloads. That is
4.0-D02and4.0-D04. Wrapping every event in a version envelope is the wrong shape: the version is agreed once at handshake, and plugins do not subscribe to the event bus at all.
Verification
- Block tests: security 26 checks, reliability 27, responsiveness 15, parsing 24, security log 12 — all passing.
- Regression: command pipeline, reminders, plugins, import/export, all 5 languages, all 5 themes — 0 failures.
- Translations: 0 untranslated strings.
On the external review
An external audit of 3.0.0 was reviewed alongside my own. Of its twelve findings, two were confirmed and are fixed here (the speech queue and the hotkey debounce), two were real but attributed to the wrong file, three were already fixed in 3.0.0, and the rest did not match the code — including a quoted fragment of settings_store.py that does not exist, and a claim of shell=True in voice/system_control.py, which contains none. Checking that particular claim is what surfaced the real shell=True in voice/commands.py....
RinaAssistant v3.0.0 — Large Update & Fixes
Changelog
All notable changes to Rina Assistant.
Releases before 3.0.0 are documented on the releases page.
3.0.0 — 2026-08-30
The largest release so far. Rina's brain was pulled out of the interface and now runs on its own; free-form questions can be answered by a local language model; and a full security and crash audit closed a set of issues, two of which could destroy data or run someone else's code.
Highlights
- Headless core. All command handling moved into
core/, which imports no Qt at all. The window is now a thin shell subscribed to events. - AI answers. Anything Rina can't parse can be answered by a local Ollama model instead of "Sorry, I didn't understand."
- Security audit. Two critical plugin vulnerabilities fixed, plus untrusted text no longer rendered as markup, and imported commands can no longer arrive pre-armed.
- Crash audit. ~600 hostile inputs, corrupted data files and concurrent access: 30 failures found, 0 remaining.
Architecture: the headless core
Rina used to think inside voice/service.py, which was a QObject. Recognition, parsing, launching and speaking were all entangled with the widget tree, so none of it could run — or be tested — without a window on screen.
core/engine.py— the whole pipeline: pending questions → plugins → user commands → reminders → system control → app launcher → built-ins → language model → web fallback. Zero Qt imports.core/events.py— a small synchronous event bus. The core announces what happened; it never touches a widget.core/protocol.py— every event and its payload declared in one place, with aPROTOCOL_VERSION. Payloads are plain JSON-serialisable values, so this contract becomes an IPC protocol unchanged when the shell moves to another process or another language.voice/service.py— reduced from ~700 lines of logic to a Qt adapter that forwards core events to signals. −538 lines.
Practical consequences today: the core can be driven headless in tests, the shell can be replaced without touching behaviour, and a background thread can no longer accidentally call into Qt.
AI answers via Ollama
When no handler claims a phrase, Rina can now ask a local model.
- Local by design. Requests go only to the address in settings (
localhost:11434by default). Nothing leaves the machine; if you point it elsewhere, the settings page says so plainly. - No new dependencies. Ollama speaks HTTP, so
urllibis enough. - Conversational. The last 6 exchanges are sent as context, so follow-up questions work.
- Spoken-answer persona. The default prompt asks for one or two sentences, no lists, no markup, in the speaker's language — the answer is read aloud.
- New
THINKINGevent. The interface shows an indicator instead of going silent for several seconds. - Settings → AI. Enable, server address, model picker (populated from the server), custom persona, timeout, and a "Check connection" button.
Disabled by default. With it off, the pipeline behaves exactly as in 2.5.0.
Security
Every issue below was reproduced in a sandbox before being fixed, not inferred from reading the code.
Critical
Plugin installation could delete the application. A plugin.json declaring "id": ".." escaped the plugins folder, and the overwrite step then removed the application root — main.py, core/, every plugin. Fixed in three layers: plugin ids are validated against a strict whitelist, the resulting path is re-checked after joining to confirm it is a direct child of the plugins folder, and nothing is removed unless the target actually contains a plugin.json.
A plugin could run without being enabled. An archive reusing the id of an already-enabled plugin replaced it, and its code executed immediately during the automatic re-scan — while the interface still said "Enable it below." Replacing a plugin now forces it back to disabled, and the confirmation message says a plugin was replaced.
Folder names are now authoritative. discover() used to trust the id inside the manifest, so a manifest could claim another plugin's identity and inherit its stored settings. The folder name wins.
High
Untrusted text is no longer rendered as markup. Qt labels interpret HTML by default and setTextFormat was never called, so a model reply, a recognised phrase, plugin output or a plugin manifest containing <img src="file://some-host/x"> would make Windows reach out to that host over SMB. All externally-sourced text — history, toasts, plugin pages, plugin cards — is now explicitly plain text.
Imported commands can no longer arrive armed. Command files were validated only by their envelope; type, target and enabled were trusted verbatim, so a shared file could plant an enabled command pointing at an arbitrary executable or UNC path. Imported entries are now reduced to known fields, checked against the known command and system-action types, capped (500 commands, 20 triggers, 200 characters each, minimum 2), and always imported disabled.
System binaries are launched by absolute path. shutdown.exe and rundll32.exe were invoked by bare name, and Windows' search order includes the current directory — a file dropped there would run instead. Resolved through %SystemRoot%\System32 now.
Medium
- The Ollama address was accepted as free text; it is now required to be
http/httpswith a host, responses are capped at 4 MB, and a non-local address is flagged in settings. - Removed a dead
dispatch_user_commandpath that skipped the confirmation prompt for destructive actions.
Reliability
Settings could be lost, and could kill the reminder scheduler. save() iterated the live dirty-key set while another thread modified it, raising RuntimeError: Set changed size during iteration. The store is now guarded by a lock and snapshots the set before writing.
Vosk speech recognition never worked. A missing import os made the model loader raise NameError on the first phrase for anyone who installed Vosk.
Corrupted data no longer breaks a whole tab. History and reminder stores now normalise and drop malformed records instead of propagating them into the interface.
Absurd dates are no longer permanent. "Remind me in 99999999999999999999 minutes" produced an entry that broke the Reminders tab on every launch and could not be deleted. Durations are now bounded, dates are clamped to ten years out, and unformattable timestamps degrade to —.
Duplicate command execution. Toggling always-listen twice left two microphone threads running, so a single phrase was handled twice. Each run now owns its own stop signal.
Interface freezes. The full application scan — including a PowerShell call for Store apps — ran on the interface thread when opening the command editor. It now reads the cached index and refreshes in the background.
Screenshots crashed from the wrong thread. Screen capture is a Qt operation and was being called from the worker; it now travels to the shell as a window action and is taken on the interface thread.
Also fixed: a failed system action reported success inside sequences; a malformed format field escaped the import handler as an unhandled ValueError; the "Refresh applications" button could stay disabled after a failed scan.
Interface
- New AI section in Settings with a live connection check.
- History messages measure their own wrapped height, so long replies are no longer clipped.
- Plugin cards and plugin-authored pages render text safely (see above).
- Documentation strings corrected where they had drifted from the code (event contract, reminder scheduler).
Housekeeping
- Removed the empty
ui/package left over from 1.0.0; the build spec now shipscore/. - README rewritten from scratch for the current application, with screenshots.
Verification
- Crash test: ~600 hostile inputs (empty, 10 000 characters, emoji, control and RTL characters,
../.., UNC paths, division by zero,2**2**2**2**2, "at 99:99"), corrupted data files, answers with no question pending, and 4 concurrent threads — 30 failures → 0. - Security probes: path traversal 0 failures; plugin replacement no longer executes on discovery.
- Regression: command pipeline, reminders, plugins, import/export, all 5 languages, all 5 themes — 0 failures.
- Translations: 0 untranslated strings.
Known limitations
- Typed commands still run the pipeline on the interface thread; the worst stall (the application scan) is gone, but launching still happens there.
- Overlapping speech replies share one busy flag, and gTTS/Piper use fixed temporary filenames — two answers in quick succession can interfere.
- History, reminders and usage statistics still use read-modify-write updates.
- "1 hour 30 minutes" is parsed as one hour; only the first unit is read.
RinaAssistant v2.5.0 — Multi updates
[2.5.0] — 2026-08
Added
- Ukrainian, Spanish and German interface languages. The localisation
engine now supports any number of languages instead of just Russian and
English. The core interface — navigation, page and section titles, buttons,
setting names, and the most frequent assistant replies — is translated;
anything not yet covered falls back to the original Russian rather than to
an invented machine translation. - A translation-coverage note under the language selector, e.g. "About 17%
of the interface is translated — the rest is shown in Russian." Choosing a
language should not promise more than it delivers.
Changed
- Speech-recognition language now follows the interface language for all five
languages, not only Russian and English.
[2.4.0] — 2026-08
Added
- Wake-word sensitivity slider. How closely a spoken word must match the
wake word was previously fixed in code; the right value depends on the
microphone and the recognition engine. The setting is clamped to 0.5–0.98 —
below that almost anything matches, above it almost nothing does. - Recording length setting (3–20 seconds). Rina previously always listened
for exactly eight seconds after the hotkey. - "Check models" button for the Vosk and Piper model paths. Picking the
wrong folder is easy, and until now it only surfaced later as an
unhelpful recognition error. The check also recognises the most common
mistake — pointing one level above the real model — and says so:
"The model seems to be inside: model-ru".
Fixed
- A misleading comment in the wake-word matcher claimed the 0.8 threshold
matched heavily distorted variants. The measured similarity is 0.5 for those
and 0.75–0.89 for realistic ones; the documented example now matches reality.
[2.3.0] — 2026-08
Added
- Installing plugins from a folder or a .zip archive, straight from the
Plugins tab. The contents are validated before anything is copied — manifest
present,main.pypresent,plugin.jsonreadable and carrying an id — so a
wrong pick cannot leave debris that reports itself as a broken plugin on
every launch. Archives that wrap the plugin in a single nested folder are
handled, and installing over an existing plugin updates it. - Richer declarative plugin pages (API v2). Alongside
Title,Text,
Note,Items,ButtonandDivider, plugins can now describe:
Input(a text field whose value is passed toon_action),Table(rows
with optional headers),Progress(a 0…1 bar), andBadge(a small status
label). Pages remain plain data and still serialise to JSON, so plugins stay
independent of the UI framework.
Changed
on_action(action, value)now receives a value, which is what makes input
fields possible.
[2.2.0] — 2026-08
Added
- Export and import of commands. Move your commands to another computer or
keep a backup. The file carries a format version and a type, so an import
can tell a commands file from a history file and refuses the wrong one with
a clear reason rather than silently doing nothing. - History search — filter the log as you type; the counter and the empty
state follow the query ("No entries match …"). - History export to readable text (grouped by day, with times and
speakers) or to JSON.
Changed
- Importing commands adds to what you have instead of replacing it, and
duplicates are detected by trigger phrases rather than by id — an id from
another machine means nothing, but the phrases are what a command actually
is to you. Imported commands get fresh ids so they cannot collide with
local ones.
[2.1.0] — 2026-08
Added
- Timers, alarms and reminders. "Set a timer for ten minutes", "remind me
in half an hour to call mum", "remind me at 15:00 to call the doctor",
"wake me at 7:30". Durations are understood as digits or words, including
"half an hour" and "an hour and a half", and absolute times resolve to the
next occurrence (tomorrow if the time has already passed today). - Asking about and cancelling what is scheduled by voice: "what timers do
I have", "cancel all timers". - A Reminders tab listing everything scheduled with a live countdown,
cancelling one or all, and a small form for adding a reminder by hand when
speaking is inconvenient. - Scheduled items are stored on disk and survive a restart — a reminder
that disappears when the app closes cannot be trusted.
Fixed
tr()raised aTypeErrorfor any string containing a{text}
placeholder, because the name collided with the translation function's own
first argument. The parameter was renamed so this class of failure cannot
recur.
RinaAssistant v2.0.0 — First Global Update
[2.0.0] — 2026-08
Rina now knows what is installed on your computer. Launching a program no
longer requires adding it by hand: say its name and she finds it, asks which
one you meant when several match, and remembers your answer.
Added
- Program discovery. Rina indexes what is installed on the machine —
Start Menu shortcuts, Microsoft Store apps, desktop shortcuts, and
executables on PATH — so "запусти телеграм" works without any setup.
Names spoken in Russian resolve to Latin-named programs through
transliteration and a table of common spoken names ("стим" → Steam,
"ворд" → Word, "обс" → OBS Studio). "Запусти браузер" launches whichever
browser is actually installed. The index is cached (a full scan takes about
a second, a cached read four milliseconds) and refreshes in the background. - Folders with portable programs (Settings → Программы). Programs that are
simply unpacked into a folder have no Start Menu entry and no registry
record — point Rina at the folder and she will find them. Bundled runtimes
and helper executables are filtered out, so a Ren'Py SDK folder contributes
renpy.exeand not the five other.exefiles shipped inside it. - Teaching Rina a program. When nothing matches, Rina offers to be shown
the file once and remembers it permanently. Remembered programs are listed
in the Commands tab and can be removed individually. - Clarifying questions. When several programs match, Rina asks instead of
guessing — "Нашла несколько: Visual Studio 2022, Visual Studio Code…" — and
accepts "второй", a name, or "отмена". The answer is remembered, so the
same phrase launches straight away next time. - System and media control: volume, mute, play/pause, next/previous track,
screenshot, lock. Shutdown, restart and sleep are available too, but always
require confirmation. - Sequence step "Пауза" — a delay between steps, so a scenario can wait for
a program to start before the next step runs. - Plugin API v3: declarative pages. A plugin now describes its tab as data
(Title,Text,Note,Items,Button,Divider) and the application
renders it. Plugins no longer import Qt, so they will survive a change of UI
framework, and a page can be serialized to JSON for a non-Python shell.
The bundled Notes plugin was rewritten as the reference implementation. - Config schema versioning with automatic migration, including a one-time
backup of the previous configuration before the first migration.
Changed
- Creating a command no longer asks for a file path. The "Программа" type
offers autocomplete over the programs Rina found; browsing for a file is
still available for anything not in the index. Store apps are supported as
command targets, and editing a command shows the program's name rather than
its application identifier. - Sequences were reworked the same way: program steps use the picker, and
the action step grew from five window-only actions to sixteen, covering
volume, playback, screenshot, lock and power. - Duplicate trigger phrases are now refused with an explanation. Previously
two commands could share a phrase, only the first ever ran, and there was no
way to tell why the second was silent. - Commands containing shutdown, restart or sleep — directly or in a step —
ask for confirmation before running. - Sequences run in a background thread, so a pause no longer freezes the window.
- The hard-coded catalogue of five launchable programs is gone; it remains only
as a fallback on systems without an index. - The Commands tab now also shows what Rina found, with a refresh button.
Fixed
- Programs with Russian names could not be launched at all. PowerShell
returns its output in the console codepage, not UTF-8, so 62 system apps —
"Блокнот", "Диспетчер задач", "Калькулятор" — were read as mangled text and
never matched anything. - Window actions were executed from the wrong thread. Commands run in the
speech-recognition thread and called window methods directly; they are now
routed to the GUI thread through a signal. - Enabling any plugin that declares settings crashed the application — the
plugin settings panel still used the old row signature after the 1.2.0
interface rework.
Notes for plugin authors
create_page() returning a QWidget still works, but it is deprecated: it ties
a plugin to Qt. Implement page() (see plugins/page_spec.py) and handle
button presses in on_action(). If both are defined, page() wins.
Upgrading
Configuration is migrated automatically on first launch. Custom commands,
history, plugins and their settings are preserved, and a copy of the previous
configuration is written to backup-v0/ next to the config files
(%APPDATA%\RinaAssistant\) in case you need to go back.
RinaAssistant v1.2.0 — Update
[1.2.0] — 2026-08-01
Added
- Calculator. Rina now answers arithmetic asked in plain speech: "посчитай
15 * 12", "сколько будет 2+2", "20% от 3000", "раздели 100 на 5", "5 в
квадрате". Spoken operators ("плюс", "умножить на", "разделить на") are
understood, since speech recognition never produces*or/. Expressions
are evaluated from a parsed syntax tree with a whitelist of operations —
never witheval()on text coming from a microphone — and division by zero
and oversized powers are handled explicitly. - Web search. Explicit queries work out of the box: "найди рецепт борща",
"загугли python", "поищи в интернете …". Unrecognized commands can also fall
back to a web search instead of "Извини, я не поняла команду". - "Web search" settings section with a search engine picker (Google,
Яндекс, DuckDuckGo, Bing) and a toggle for the unrecognized-command fallback.
Changed
- Command matching is now fuzzy. Triggers are normalized (case, ё/е,
punctuation, spacing) and compared with a similarity threshold, so
"зопусти дискорт" still matches a command saved as "запусти дискорд".
Matching slides a window over the phrase, so a trigger is found inside a
longer sentence. "Exact match" mode still requires the whole phrase, but
tolerates recognition noise. The threshold is deliberately strict:
launching the wrong program is worse than having to repeat yourself.
The same normalization now applies to built-in commands. - The interface was reworked to look more restrained. One accent color
replaces the neon purple→pink→blue gradients across navigation, cards,
buttons, toggles, chat bubbles, avatars, and the window border. Cards are
flat surfaces with a hairline border instead of glass-style gradients and
layered shadows, corner radii are tighter (8/12/18/24 → 6/8/12/16), the
sidebar wordmark is plain text, and the status indicator no longer pulses.
Hierarchy now comes from scale and spacing rather than color and glow. - Decorative emoji removed from section headings, settings rows, buttons,
status labels, About links, empty states, and history badges. Navigation
icons remain, where they help scanning the sidebar. - The unrecognized-command fallback never triggers in always-listen mode:
background speech and noise must not be able to open a browser. - English translations added for all new strings, and translation keys
re-synchronized after the emoji cleanup so the English UI stays fully
translated.
Removed
- The
GradientTextcomponent and the theme's gradient/glow helpers, along
with the secondary accent colors they needed. - Unused icon arguments left over in
SettingRow,_path_row, and
_action_rowafter the emoji cleanup.
RinaAssistant v1.1.4 — Auto check updates fix
[1.1.4] — 2026-07-31
Fixed
- Startup update notification never appeared when "Minimize to tray" was
disabled (regression introduced in 1.1.2). The notification was delivered
only as a tray balloon, and Qt silently discardsshowMessage()when the
tray icon is hidden — so the check ran, found the new version, and the result
went nowhere. Manual "Check now" was unaffected because it writes its result
directly under the button.
Added
- Update window. When a new version is found at startup, Rina now shows a
proper dialog with the version info and Download (opens the latest
release page) / Later buttons, instead of a tray balloon that is easy to
miss — or lost entirely when the tray icon is hidden.
Changed
- Update notifications now pick a delivery channel that actually works: the
window when Rina is on screen, a tray balloon when it is hidden or minimized,
and — if neither is possible — the notice is shown the next time the window
is restored from the tray. SystemTray.notify()now reports whether the notification was actually
delivered (it returnsFalsewhen the tray icon is not visible), so silent
losses like this cannot happen unnoticed again.
RinaAssistant v1.1.3 — Patch
[1.1.3] — 2026-07-31
Added
- "Test voice" button on the Rina tab. Plays a short sample phrase using the
currently selected TTS engine, voice, volume, and speed — so you can preview a
voice before saving. Reports synthesis errors directly in the UI (previously
a failing Piper voice produced silence with no explanation), and prompts you
to pick a TTS engine if "Silent" is selected.
Changed
- The main hotkey is now configured in one place. The plain-text hotkey field
on the Settings tab has been removed; the assistant hotkey is set exclusively
on the Hotkeys tab using the click-and-press capture field. This removes the
duplicate control and the risk of the two fields disagreeing. - Global hotkey status moved to the Hotkeys tab, shown directly beneath the
main hotkey ("✓ Global activation is active" / "requires pynput"), where it is
actually relevant. The redundant pynput note at the bottom of the page was
replaced with usage hints (Esc to cancel, empty field to unassign). - The floating command bar and the About page now use the Rina emblem instead of
the placeholder 🌸 emoji, completing the branding pass started in 1.1.2.
Removed
- Leftover unused settings keys
languageandtelemetryfrom the defaults.
(Their UI controls were removed in 1.1.2; this drops the now-dead storage.)
RinaAssistant v1.1.2 — fix patch
Version [1.1.2]
Fixed
- Speech recognition was completely broken. All STT engines (Google, Vosk,
Whisper, PocketSphinx) failed to record from the microphone due to a wrong
import (settings_storeinstead ofcore.settings_store) that was silently
swallowed. Microphone capture now works again. - Input/output audio device selection had no effect — the same import bug
discarded the chosen device. Selected devices are now respected. - Piper TTS never spoke:
voices()raised an uncaught error andspeak()
always failed. Fixed by the same import correction. - "Check for updates" did nothing on launch. The toggle existed but no
startup check was wired. The app now checks for updates on start (when
enabled) and notifies via the tray only when a newer version is available. - Autostart pointed to a non-existent path when running from source
(an extra directory level in the project-root lookup). - "Reset settings" wiped user data. It now resets only application settings
and preserves your custom commands, history, and enabled plugins. A separate
full factory reset is available internally (reset_all). - Translucent UI tints rendered as the wrong solid colors (8-digit hex was
interpreted as#AARRGGBB, not#RRGGBBAA). The "Online" badge, hover
states, and history bubbles now show their intended colors. - History message bubbles could be clipped off the right edge of the window.
- Removed a dead "Documentation" link on the About page (empty URL).
Removed
- Duplicate language selector on the Rina tab (see Changed).
- Non-functional "Send telemetry" toggle (it never sent anything).
RinaAssistant v1.1.1 — Hotfix patch
Rina Assistant v1.1.1 Hotfix patch
This hotfix resolves a critical issue introduced in the previous release.
Fixed
- Fixed an import error that prevented the First Launch Setup Wizard from opening.
- Fixed an application crash during the initial startup on a clean installation.
- Improved startup stability and initialization process.
Notes
This update is recommended for all users running v1.1.0.
RinaAssistant v1.1.0 — Hotfix Update
Rina Assistant 1.1.0
Rina Assistant 1.1.0 is here! This release focuses on polishing the application, improving the interface, and fixing several issues reported during development.
✨ What's New
- Improved application design and UI.
- Fixed various visual glitches.
- Fixed the command creation feature (import-related issue).
- General bug fixes and stability improvements.
Thank you for your support! Stay tuned—Rina Assistant 2.0 is already in development with even more exciting features planned.