feat(vault): zero-setup UX — save a login on the page that needs it, managers auto-detected, one "Passwords & Logins" surface
Nobody should have to learn `hermes vault add` or find a toggle before "log into GitHub" works. - browser_vault_save_login: when the agent reaches a sign-in page with no saved login it asks the user on THEIR surface (CLI two-step panel on the sudo modal: identifier shown, password masked; Desktop card with labelled Email/username + Password fields). The answer goes to the encrypted vault bound to the page origin and is filled at once; the model gets back only the handle and identifier. Declining returns save_declined; headless sessions get prompt_unavailable. Never a password in chat. - Vault tools ride with the browser toolset (check_browser_requirements) instead of appearing only once the vault has items — an empty vault is exactly when save_login is needed. browser_vault_list hints at it when empty. - 1Password / Bitwarden are login sources as soon as their CLI is installed; `vault.<name>.enabled` is opt-OUT only. Settings shows Detected/Locked/Unlocked/Off/Not detected with a switch only for installed managers; `hermes vault sources` reports detection, `--disable`/`--enable` flip the opt-out. - Desktop nav/page renamed "Passwords & Logins"; empty state tells the user they do not need to add anything; all five locales updated. Docs rewritten from "how it works" to "say log into X". - New per-thread SaveLoginPrompt callback (agent/vault_backends/unlock.py) installed beside the unlock prompt on every CLI site and the gateway bridge (vault.save_login.request/respond/expire), propagated to worker threads via tools.thread_context. Live: CLI PTY (real model, packaged Chromium, local login server) — panel shown, identifier + masked password typed, server received the correct password, password absent from terminal transcript and from every file under HERMES_HOME outside vault/. Native Electron (headless, isolated HOME/HERMES_HOME, own Vite + CDP port) — card shown, "Save & sign in", server received the password, Settings lists the saved item, password absent from the rendered UI.
This commit is contained in:
@@ -3000,8 +3000,9 @@ class HermesCLI(CLIProcessNotificationsMixin, CLIAgentSetupMixin, CLICommandsMix
|
||||
set_sudo_password_callback(self._sudo_password_callback)
|
||||
set_approval_callback(self._approval_callback)
|
||||
set_secret_capture_callback(self._secret_capture_callback)
|
||||
from agent.vault_backends.unlock import set_unlock_prompt_callback
|
||||
from agent.vault_backends.unlock import set_save_login_prompt_callback, set_unlock_prompt_callback
|
||||
set_unlock_prompt_callback(self._vault_unlock_callback)
|
||||
set_save_login_prompt_callback(self._vault_save_login_callback)
|
||||
try:
|
||||
from tools.computer_use_tool import set_approval_callback as _set_cu_cb
|
||||
|
||||
@@ -3942,9 +3943,10 @@ class HermesCLI(CLIProcessNotificationsMixin, CLIAgentSetupMixin, CLICommandsMix
|
||||
with suppress(Exception):
|
||||
from tools.voice_mode import cleanup_temp_recordings
|
||||
cleanup_temp_recordings()
|
||||
from agent.vault_backends.unlock import lock as _vault_lock, set_unlock_prompt_callback
|
||||
from agent.vault_backends.unlock import (lock as _vault_lock, set_save_login_prompt_callback,
|
||||
set_unlock_prompt_callback)
|
||||
for _unset in (set_sudo_password_callback, set_approval_callback, set_secret_capture_callback,
|
||||
set_unlock_prompt_callback):
|
||||
set_unlock_prompt_callback, set_save_login_prompt_callback):
|
||||
_unset(None)
|
||||
_vault_lock() # session tokens for external password managers die with the session
|
||||
# On SIGHUP/SIGTERM the agent thread may be reaped before its own persistence runs.
|
||||
|
||||
Reference in New Issue
Block a user