Skip to content

Releases: Synero/hermes-live-voice

0.2.6: Hermes signs the Codex requests (needs Hermes 0.21.7)

Choose a tag to compare

@Synero Synero released this 10 Oct 19:54

Pre-release. Requires Hermes 0.21.7 or newer, the first Hermes release that ships NousResearch/hermes-agent#136117. On Hermes 0.21.6 or older, Hermes will not load this version; stay on v0.2.5, which is what the official catalog installs today.

Answers #20 from the Hermes maintainers: the plugin no longer holds, refreshes or rewrites a Codex token.

  • ChatGPT subscription lane: Hermes signs the Realtime client-secret request itself (credentialed_provider_request), with its own locked refresh. No Authorization header comes from the plugin.
  • Plan usage panel reads Hermes's fetch_account_usage("openai-codex", read_only=True) instead of calling the usage endpoint with the token.
  • "Sign out" no longer deletes ~/.codex/auth.json (that also signed the Codex CLI out). It points at hermes auth logout openai-codex.
  • The bundled non-refreshing talk_auth is pinned in-process, so an installed hermes-talk cannot add a second refresher.
  • plugin.yaml: requires_auth: [openai-codex], requires_hermes: ">=0.21.7".
  • Unchanged: API-key lanes and the gpt-live-1 codex app-server lane.

Verification: 77 tests (12 new for this flow, 11 of them fail on v0.2.5), CI green on Python 3.11 and 3.12, and a live end-to-end run against Hermes core with #136117: OpenAI returned a client secret and both auth files were byte-identical before and after.

This becomes a regular release, and the catalog pin moves to it, once Hermes 0.21.7 is out. PR: #21

0.2.5: host bot name, clean voice bubbles, real demo

Choose a tag to compare

@Synero Synero released this 09 Oct 17:47
88cf7ba
  • No bot name is hardcoded: without a bot profile the voice identity uses the host agent.name, falling back to "Hermes" (#16).
  • The "[voice] reply briefly" note stays out of the chat bubble on hosts with the voice-live surface; it only reaches the model (#17).
  • README: real Live Voice demo recording and screenshots (#18).

Verified at this commit: pytest 65 passed, CI on Python 3.11 and 3.12, node --check, py_compile, plugin load test, privacy grep clean.

0.2.4: English UI fallback, handoff hardening

Choose a tag to compare

@Synero Synero released this 09 Oct 14:32
4a536f1
  • Tooltips and visible UI messages now follow the browser language, with English as the fallback (#13, fixes #12). Thanks @photogeek134.
  • Codex Live start: the compatibility retry now only drops optional fields the app-server actually names, and fails closed with a clear error (LIVE_HANDOFF_NO_SOPORTADO) if client-managed handoff is not supported, instead of falling back (#14). Thanks @mziada for the careful report.
  • Clear explanation when the backend half is not mounted (Method Not Allowed) (#11, fixes #9).
  • SECURITY.md with private vulnerability reporting (#10).

Verified at this commit: pytest 63 passed, CI on Python 3.11 and 3.12, node --check, plugin load test.

v0.2.3

Choose a tag to compare

@Synero Synero released this 18 Sep 18:25

Fixes that landed after 0.2.2:

  • Live Voice panels stay open when focus moves (hover/focus no longer closes the config popover).
  • Codex device code is captured without ANSI escape codes, so the login code is readable.
    Docs: README rewritten (architecture, install via the plugin catalog, troubleshooting).

0.2.2 — privacy + language polish

Choose a tag to compare

@Synero Synero released this 17 Sep 08:02
486a6ec

Maintenance release. This plugin installs on other people's machines, and 0.2.2 removes the last places where ours could leak into their install.

Fixed

  • No owner identity in shipped strings. The live transcript labeled the user's own bubble with a literal maintainer name; it is now localized (Tú/You) through the plugin's own i18n helper. The _bot_display_name docstring no longer lists private bot names as "formats seen", and a static test fails the build if a literal owner name reappears in the desktop half.
  • Stale-thread recovery keeps the session language. _cl_thread_ensure() defaults to es; the recovery path called it bare, so an English session that hit a dead thread was re-registered as Spanish and the next English call discarded the recovered thread (new context, new plan work). Covered by a test that drives the thread not found branch.

Included from the community

  • #4 by @tillstriegel: the voice identity prompt no longer hardcodes the owner's name, and the model-facing voice context honors the session language.

Verification

  • python -m pytest -q → 51 passed (49 before; the 2 new tests fail when either fix is reverted).
  • py_compile, node --check desktop/plugin.js, tools/plugin-load-test.sh clean on 3.11 and 3.12.
  • Repo-wide re-grep for personal/environment identifiers: 0 hits outside .git/tests.

Full diff: 486a6ec

0.2.1 — audit fixes (issue #1)

Choose a tag to compare

@Synero Synero released this 12 Sep 23:01

Audit fixes for the findings in #1 — thanks to @whyyagswhy for the external review and the reproduction script.

Fixed

  • Fresh installs — the backend now imports its bundled dashboard/talk_vendor/ fallback on a machine with no other plugin installed, instead of dying with ModuleNotFoundError: talk_auth. An installed hermes-talk still takes precedence.
  • Concurrent /session — two simultaneous optional-Realtime mints no longer deadlock the event loop (the lock, the profile override and its restore now live inside the worker that mints, so cancellation cannot restore the override mid-mint).
  • RPC correlation — /codexlive/* responses are matched by request id over the whole reader buffer instead of a positional scan, so a delivered response can no longer be lost to buffer pruning.
  • /codexlive/interrupt — runs off the event loop (was blocking it for up to 8 s).
  • CODEX_HOME — resolved consistently by codex login, backup and logout (previously status/backup read CODEX_HOME while the login popped it).
  • Interrupt body — the desktop half sends a plain object body like every other call site; the pre-stringified body was rejected by the transport, so the interrupt never reached the app-server.
  • Mute — a muted mic can no longer be silently un-muted by barge-in: guards in doBargeIn()/maybeBarge() and the level meter reads zero while muted (the analyser sees the raw mic, so disabling the track alone did not silence it).
  • Capability drops are visible — when an older app-server rejects clientManagedHandoffs, the session response now carries droppedFields / handoffDegraded / warning and the desktop shows a notice. Previously the client believed it was driving handoff while the server had silently switched (degrading the session is deliberate: refusing to start would break app-servers that legitimately predate these fields).

Verification — 8 regression tests (python -m pytest -q, stdlib + pytest only), CI on 3.11/3.12, py_compile, node --check, the ESM load harness, and the reproduction script from #1 unmodified (exit=0, both checks pass; on the previous commit both fail).

Update

  • Backend half: copy dashboard/ + plugin.yaml over $HERMES_HOME/plugins/talk-desktop/ (keep your settings.json and data/) and restart the dashboard.
  • Desktop half: replace $HERMES_HOME/desktop-plugins/talk-desktop/plugin.js with desktop/plugin.js from this tag.