hermes-agent/hermes_cli
Ben Barclay 76ac204846 fix(wake): run openWakeWord on tflite on macOS ARM64
openWakeWord's ONNX backend returns near-zero scores on Apple Silicon
(dscripka/openWakeWord#336), so "Hey Hermes" never crossed the 0.5
threshold: the listener armed, the microphone worked, and nothing fired.

Bisecting the pipeline puts the fault in exactly one stage — feeding the
same audio through both backends, the melspectrogram front-end is
bit-identical (maxdiff 0.00000) and the wake classifier agrees on
identical features, while the shared embedding model diverges by 45.44.
Cross-feeding confirms it: tflite features scored through the *onnx*
classifier give 0.9948 vs 0.000009 for onnx features. A telling
secondary symptom is that scores fall as input gets louder (0.5x ->
0.00031, 8x -> 0.000066), which is garbage inference rather than a weak
detection.

Selecting tflite in config alone does not fix it. openWakeWord hardcodes
`import tflite_runtime.interpreter` but declares tflite-runtime for
`platform_system == "Linux"` only; on macOS the equivalent wheel is
ai-edge-litert, so that import always fails and model.py silently
downgrades back to onnx. The result is a detector that reports itself
listening and can never fire.

- default the backend per platform (tflite on macOS ARM64, onnx
  elsewhere) instead of hardcoding onnx, and pick the matching bundled
  model artifact
- bridge tflite_runtime -> ai_edge_litert through sys.modules, in-process,
  with no writes to site-packages
- refuse the silent onnx downgrade on macOS ARM64 and report the missing
  runtime through check_wake_word_requirements() so the GUI surfaces an
  actionable hint rather than arming a dead ear
- lazy-install ai-edge-litert via its own feature key, because lazy-dep
  specs cannot carry PEP 508 markers (_spec_is_safe rejects ";")

An explicit `inference_framework` in config still wins, so anyone pinning
a backend keeps it.

Verified on macOS 26.5.2 / M-series: "hey hermes" scores 0.0005 on onnx
and 0.9423 on tflite from the same clip, with cross-phrase controls at
0.0003. Live over-the-air through the real microphone fires 4/4
utterances (peak 0.9532).
2026-07-28 13:35:37 +10:00
..
dashboard_auth
proxy
subcommands
__init__.py
_early_recovery.py
_parser.py
_subprocess_compat.py
active_sessions.py
agent_import.py
approval_mode.py
approvals_suggest.py
auth.py
auth_commands.py
azure_detect.py
backup.py
banner.py
blueprint_cmd.py
browser_connect.py
build_info.py
bundles.py
callbacks.py
checkpoints.py
claw.py
cli_agent_setup_mixin.py
cli_billing_mixin.py
cli_commands_mixin.py Merge remote-tracking branch 'origin/main' into wake-toggle-config 2026-07-27 14:57:11 -07:00
cli_output.py
clipboard.py
codex_models.py
codex_runtime_plugin_migration.py
codex_runtime_switch.py
colors.py
commands.py Merge remote-tracking branch 'origin/main' into wake-toggle-config 2026-07-27 14:57:11 -07:00
completion.py
config.py fix(wake): run openWakeWord on tflite on macOS ARM64 2026-07-28 13:35:37 +10:00
console_engine.py
container_boot.py
context_switch_guard.py
copilot_auth.py
credential_lifecycle.py
cron.py
curator.py
curses_ui.py
dashboard_register.py
debug.py
default_soul.py
dep_ensure.py
diagnostics_upload.py
dingtalk_auth.py
doctor.py fix(browser): stop stale cdp_url from stalling every startup by 10+ seconds 2026-07-27 14:32:05 -07:00
dump.py revert: PR #72817 — session activity watchdog, stall notify, compress timeout 2026-07-28 00:15:00 +05:00
env_loader.py
fallback_cmd.py refactor(fallback): single owner for backend identity and failure-scoped skips 2026-07-26 23:41:54 -07:00
fallback_config.py
focus_view.py
gateway.py
gateway_enroll.py
gateway_windows.py
goals.py
gui_uninstall.py
hooks.py
init_command.py
input_sanitize.py
inventory.py
journey.py
kanban.py
kanban_db.py
kanban_decompose.py
kanban_diagnostics.py
kanban_specify.py
kanban_swarm.py
logs.py
main.py fix(update): close the stale-bytecode class with a launch-time checkout-fingerprint sweep 2026-07-27 11:33:40 -07:00
managed_scope.py
managed_uv.py
mcp_catalog.py
mcp_config.py
mcp_picker.py
mcp_security.py
mcp_startup.py
memory_oauth.py
memory_setup.py
middleware.py
migrate.py
moa_cmd.py
moa_config.py
model_catalog.py
model_cost_guard.py
model_normalize.py fix(model): don't strip alias-derived prefixes for the custom provider bucket 2026-07-27 19:32:12 +05:30
model_search.py
model_setup_flows.py
model_switch.py nous portal anthropic wire 2026-07-27 11:53:48 -04:00
models.py
nous_account.py
nous_auth_keepalive.py
nous_billing.py
nous_subscription.py
onepassword_secrets_cli.py
oneshot.py
pairing.py
partial_compress.py
pets.py
platforms.py
plugins.py fix subagent lifecycle ownership invariants 2026-07-26 23:27:30 -07:00
plugins_cmd.py fix(update): close the stale-bytecode class with a launch-time checkout-fingerprint sweep 2026-07-27 11:33:40 -07:00
portal_cli.py
profile_describer.py
profile_distribution.py
profiles.py
projects_cmd.py
projects_db.py
prompt_size.py
provider_catalog.py
providers.py nous portal anthropic wire 2026-07-27 11:53:48 -04:00
proxy_cli.py
psutil_android.py
pt_input_extras.py
pty_bridge.py
pty_session.py
relaunch.py
route_identity.py
runtime_provider.py nous portal anthropic wire 2026-07-27 11:53:48 -04:00
secret_prompt.py
secrets_cli.py
security_advisories.py
security_audit.py
security_audit_startup.py
send_cmd.py
service_manager.py fix(hermes_cli): drop privileges before clearing s6-log lock 2026-07-27 19:19:01 +05:30
session_export.py
session_export_html.py
session_export_md.py
session_filters.py
session_listing.py
session_recap.py
session_recovery.py fix(sessions): verify fully reconstructed recovery 2026-07-26 23:34:29 -07:00
setup.py
setup_hidden_env.py
setup_whatsapp_cloud.py
skills_config.py
skills_hub.py
skin_cmd.py
skin_engine.py
slack_cli.py
sqlite_runtime.py
sqlite_safe_read.py
sqlite_util.py
status.py revert: PR #72817 — session activity watchdog, stall notify, compress timeout 2026-07-28 00:15:00 +05:00
stdio.py
suggestions_cmd.py
telegram_managed_bot.py
timeouts.py
tips.py
tools_config.py
toolset_validation.py
uninstall.py
urllib_security.py
voice.py
web_git.py
web_server.py Merge remote-tracking branch 'origin/main' into wake-toggle-config 2026-07-27 14:57:11 -07:00
webhook.py
win_pty_bridge.py
windows_ssh_runtime.py
write_approval_commands.py
xai_retirement.py