From 70d0f556d795a94ac90f502927b86d7e75bf890a Mon Sep 17 00:00:00 2001 From: bixycler Date: Fri, 10 Apr 2026 09:01:19 +0000 Subject: [PATCH] =?UTF-8?q?fix(branding):=20use=20the=20Caduceus=20?= =?UTF-8?q?=E2=98=A4=20(U+2624),=20not=20the=20Rod=20of=20Asclepius=20?= =?UTF-8?q?=E2=9A=95=20(U+2625)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every inline glyph — CLI banner/status bar/response labels/goodbye, setup and doctor boxes, gateway update prompts, WhatsApp reply prefix, TUI theme, locale strings and the docs — used ⚕, the staff of Asclepius (medicine). Hermes carries the Caduceus ☤. The ASCII-art logo was already correct. Mechanical swap across 60 files (no logic change); both glyphs are East-Asian-width Neutral so no layout shifts. Skins that set their own `response_label` / `goodbye` are unaffected. Direction from PR #7064 (@bixycler), the earliest of #7064 / #9611 / #15574, redone against current main. Fixes #9565 --- cli.py | 2 +- gateway/platforms/qqbot/adapter.py | 2 +- gateway/platforms/whatsapp_common.py | 2 +- gateway/run_notifications.py | 2 +- hermes_cli/__init__.py | 2 +- hermes_cli/agent_import.py | 2 +- hermes_cli/claw.py | 2 +- hermes_cli/cli_agent_setup_mixin.py | 2 +- hermes_cli/cli_billing_mixin.py | 6 +++--- hermes_cli/cli_chat_turn_mixin.py | 6 +++--- hermes_cli/cli_commands_mixin.py | 8 ++++---- hermes_cli/cli_session_mixin.py | 4 ++-- hermes_cli/cli_status_bar_mixin.py | 12 ++++++------ hermes_cli/cli_stream_mixin.py | 4 ++-- hermes_cli/cli_tui_mixin.py | 2 +- hermes_cli/config.py | 2 +- hermes_cli/config_defaults.py | 2 +- hermes_cli/gateway.py | 4 ++-- hermes_cli/main_platform_setup.py | 6 +++--- hermes_cli/main_tui_launch.py | 2 +- hermes_cli/setup.py | 6 +++--- hermes_cli/setup_quick.py | 2 +- hermes_cli/setup_whatsapp_cloud.py | 2 +- hermes_cli/skin_engine.py | 4 ++-- hermes_cli/status.py | 2 +- hermes_cli/tools_config.py | 4 ++-- hermes_cli/uninstall.py | 6 +++--- hermes_cli/update_cmd.py | 6 +++--- locales/af.yaml | 2 +- locales/ar.yaml | 2 +- locales/de.yaml | 2 +- locales/en.yaml | 2 +- locales/es.yaml | 2 +- locales/fr.yaml | 2 +- locales/ga.yaml | 2 +- locales/hu.yaml | 2 +- locales/it.yaml | 2 +- locales/ja.yaml | 2 +- locales/ko.yaml | 2 +- locales/pt.yaml | 2 +- locales/ru.yaml | 2 +- locales/tr.yaml | 2 +- locales/uk.yaml | 2 +- locales/zh-hant.yaml | 2 +- locales/zh.yaml | 2 +- plugins/platforms/discord/adapter.py | 4 ++-- plugins/platforms/feishu/adapter.py | 2 +- plugins/platforms/telegram/adapter.py | 4 ++-- tests/hermes_cli/test_ensure_utf8_locale.py | 6 +++--- tests/run_agent/test_unicode_ascii_codec.py | 4 ++-- ui-tui/src/components/appChrome.tsx | 4 ++-- ui-tui/src/components/appLayout.tsx | 2 +- ui-tui/src/theme.ts | 4 ++-- website/docs/reference/cli-symbols.md | 2 +- website/docs/user-guide/cli.md | 4 ++-- website/docs/user-guide/features/skins.md | 4 ++-- website/docs/user-guide/messaging/whatsapp.md | 2 +- .../current/user-guide/cli.md | 4 ++-- .../current/user-guide/features/skins.md | 4 ++-- .../current/user-guide/messaging/whatsapp.md | 2 +- 60 files changed, 96 insertions(+), 96 deletions(-) diff --git a/cli.py b/cli.py index 2edadb4966..f3c865b1dc 100644 --- a/cli.py +++ b/cli.py @@ -2297,7 +2297,7 @@ def _build_compact_banner() -> str: dim_color = _color("banner_dim", "#B8860B") if (getattr(_skin, "name", "default") if _skin else "default") == "default": - tiny_line = "⚕ NOUS HERMES" + tiny_line = "☤ NOUS HERMES" else: tiny_line = _skin.get_branding("agent_name", "Hermes Agent") if _skin else "Hermes Agent" line1 = f"{tiny_line} - AI Agent Framework" diff --git a/gateway/platforms/qqbot/adapter.py b/gateway/platforms/qqbot/adapter.py index ab6e15c073..ee649dcf62 100644 --- a/gateway/platforms/qqbot/adapter.py +++ b/gateway/platforms/qqbot/adapter.py @@ -1499,7 +1499,7 @@ class QQAdapter(BasePlatformAdapter): are written to ``~/.hermes/.update_response`` by the interaction callback.""" del session_key, metadata # present for contract parity only. default_hint = f" (default: {default})" if default else "" - content = f"⚕ **Update Needs Your Input**\n\n{prompt}{default_hint}" + content = f"☤ **Update Needs Your Input**\n\n{prompt}{default_hint}" return await self.send_with_keyboard( chat_id, content, build_update_prompt_keyboard(), reply_to=self._last_msg_id.get(chat_id) ) diff --git a/gateway/platforms/whatsapp_common.py b/gateway/platforms/whatsapp_common.py index 57b0942a69..dacc3255c0 100644 --- a/gateway/platforms/whatsapp_common.py +++ b/gateway/platforms/whatsapp_common.py @@ -55,7 +55,7 @@ class WhatsAppBehaviorMixin: MAX_MESSAGE_LENGTH: int = 4096 supports_code_blocks = True # WhatsApp renders fenced code blocks (monospace) - DEFAULT_REPLY_PREFIX: str = "⚕ *Hermes Agent*\n────────────\n" + DEFAULT_REPLY_PREFIX: str = "☤ *Hermes Agent*\n────────────\n" _OUTBOUND_INVISIBLE_CHARS_RE = re.compile(r"[\u200b\u2060\u2063\ufeff]") _OUTBOUND_ODD_SPACE_RE = re.compile(r"[\u00a0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]") diff --git a/gateway/run_notifications.py b/gateway/run_notifications.py index c3bd778e64..1b66585b8b 100644 --- a/gateway/run_notifications.py +++ b/gateway/run_notifications.py @@ -529,7 +529,7 @@ class GatewayNotificationsMixin: default_hint = f" (default: {default})" if default else "" _p = getattr(adapter, "typed_command_prefix", "/") await target.send( - f"⚕ **Update needs your input:**\n\n{prompt_text}{default_hint}\n\n" + f"☤ **Update needs your input:**\n\n{prompt_text}{default_hint}\n\n" f"Reply `{_p}approve` (yes) or `{_p}deny` (no), or type your answer directly." ) # Keep the prompt marker on disk until answered so a restarted watcher can re-forward it. diff --git a/hermes_cli/__init__.py b/hermes_cli/__init__.py index faf2f5769c..19cf706f6a 100644 --- a/hermes_cli/__init__.py +++ b/hermes_cli/__init__.py @@ -10,7 +10,7 @@ __release_date__ = "2026.9.11" def _ensure_utf8(): """Force UTF-8 stdout/stderr to prevent UnicodeEncodeError crashes. - The CLI prints box-drawing characters and the ⚕ glyph in the setup wizard, doctor, and status + The CLI prints box-drawing characters and the ☤ glyph in the setup wizard, doctor, and status banners; under a non-UTF-8 codec that raises before the command can even start (e.g. `hermes setup` on a fresh Pi). """ diff --git a/hermes_cli/agent_import.py b/hermes_cli/agent_import.py index aacb59361b..1cd6978c7b 100644 --- a/hermes_cli/agent_import.py +++ b/hermes_cli/agent_import.py @@ -535,7 +535,7 @@ def import_agent_command(args) -> None: print() print(color("┌─────────────────────────────────────────────────────────┐", Colors.MAGENTA)) - print(color("│ ⚕ Hermes — Import From Another Agent │", Colors.MAGENTA)) + print(color("│ ☤ Hermes — Import From Another Agent │", Colors.MAGENTA)) print(color("└─────────────────────────────────────────────────────────┘", Colors.MAGENTA)) if not source_dir.is_dir(): print() diff --git a/hermes_cli/claw.py b/hermes_cli/claw.py index 465417cc32..f792b05acc 100644 --- a/hermes_cli/claw.py +++ b/hermes_cli/claw.py @@ -56,7 +56,7 @@ def _print_banner(title: str) -> None: """Print the magenta boxed banner shared by the claw subcommands.""" print() rule = "─" * 57 - for line in (f"┌{rule}┐", f"│ ⚕ Hermes — {title:<35s}│", f"└{rule}┘"): + for line in (f"┌{rule}┐", f"│ ☤ Hermes — {title:<35s}│", f"└{rule}┘"): print(color(line, Colors.MAGENTA)) diff --git a/hermes_cli/cli_agent_setup_mixin.py b/hermes_cli/cli_agent_setup_mixin.py index 606089336a..d18a6a3c90 100644 --- a/hermes_cli/cli_agent_setup_mixin.py +++ b/hermes_cli/cli_agent_setup_mixin.py @@ -347,7 +347,7 @@ class CLIAgentSetupMixin: source of truth. True when a provider was configured.""" from cli import _cprint, logger _cprint("") - _cprint("⚕ No inference provider is configured yet — let's fix that.") + _cprint("☤ No inference provider is configured yet — let's fix that.") _cprint(" You'll pick a provider (Nous Portal OAuth is the fastest; " "no API key needed) and a model.") try: diff --git a/hermes_cli/cli_billing_mixin.py b/hermes_cli/cli_billing_mixin.py index e6dc509b47..81c72ad31f 100644 --- a/hermes_cli/cli_billing_mixin.py +++ b/hermes_cli/cli_billing_mixin.py @@ -243,7 +243,7 @@ class CLIBillingMixin: self._print_logged_out(state, "Could not load subscription", "/subscription") return if state.context == "team": # no personal plan — teams run on a shared balance - self._block_header("⚕", "Team subscription") + self._block_header("☤", "Team subscription") self._print_org_line(state) print(f" This terminal is connected to {state.org_name or 'a team org'}. Teams run on a shared") print(" balance · use /topup to add funds.") @@ -288,7 +288,7 @@ class CLIBillingMixin: _cprint(f" {_from} ──▶ {_to} {_d('· ' + _when)}") self._dim(f"You keep {_from} (and its credits) until then.") _cprint("") - _cprint(f" ⚕ {_b(status)}") + _cprint(f" ☤ {_b(status)}") print(f" {_RULE}") for _bar_ln in self._usage_bar_lines(usage, plan_name): print(_bar_ln) @@ -321,7 +321,7 @@ class CLIBillingMixin: if not tiers: self._subscription_open_portal(state, manage_url, verb="Start a subscription") return - self._block_header("⚕", "Choose a plan") + self._block_header("☤", "Choose a plan") for i, t in enumerate(tiers, 1): print(f" {i}. {format_tier_row(t)}") self._dim('Starting a subscription opens the portal to add your card.') diff --git a/hermes_cli/cli_chat_turn_mixin.py b/hermes_cli/cli_chat_turn_mixin.py index 08e936f208..c39b9886f3 100644 --- a/hermes_cli/cli_chat_turn_mixin.py +++ b/hermes_cli/cli_chat_turn_mixin.py @@ -243,7 +243,7 @@ class CLIChatTurnMixin: def display_callback(sentence: str): if not turn.box_opened: turn.box_opened = True - label = " ⚕ Hermes " + label = " ☤ Hermes " if self.show_timestamps: label = f"{label}{datetime.now().strftime(self.timestamp_format)} " w = self._scrollback_box_width(getattr(self.console, "width", 80)) @@ -605,11 +605,11 @@ class CLIChatTurnMixin: try: from hermes_cli.skin_engine import get_active_skin _skin = get_active_skin() - label = _skin.get_branding("response_label", "⚕ Hermes") + label = _skin.get_branding("response_label", "☤ Hermes") _resp_color = _maybe_remap_for_light_mode(_skin.get_color("response_border", "#CD7F32")) _resp_text = _maybe_remap_for_light_mode(_skin.get_color("banner_text", "#FFF8DC")) except Exception: - label = "⚕ Hermes" + label = "☤ Hermes" _resp_color = _maybe_remap_for_light_mode("#CD7F32") _resp_text = _maybe_remap_for_light_mode("#FFF8DC") diff --git a/hermes_cli/cli_commands_mixin.py b/hermes_cli/cli_commands_mixin.py index bcbddee47d..f68fa78d33 100644 --- a/hermes_cli/cli_commands_mixin.py +++ b/hermes_cli/cli_commands_mixin.py @@ -378,11 +378,11 @@ def _print_side_result_panel(cli, *, header_lines, body, title_suffix, empty_not try: from hermes_cli.skin_engine import get_active_skin _skin = get_active_skin() - label = _skin.get_branding("response_label", "⚕ Hermes") + label = _skin.get_branding("response_label", "☤ Hermes") _resp_color = _maybe_remap_for_light_mode(_skin.get_color("response_border", "#CD7F32")) _resp_text = _maybe_remap_for_light_mode(_skin.get_color("banner_text", "#FFF8DC")) except Exception: - label, _resp_color, _resp_text = "⚕ Hermes", "#CD7F32", "#FFF8DC" + label, _resp_color, _resp_text = "☤ Hermes", "#CD7F32", "#FFF8DC" rich_console.print(Panel( _render_final_assistant_content(body, mode=cli.final_response_markdown), title=f"[{_resp_color} bold]{label} {title_suffix}[/]", title_align="left", @@ -2654,12 +2654,12 @@ class CLICommandsMixin: choices = [("once", "Update Now", "exit the current session and update Hermes Agent"), ("cancel", "Cancel", "keep the current session")] raw = self._prompt_text_input_modal( - title="⚕ Update Hermes Agent", + title="☤ Update Hermes Agent", detail="This will exit the current session and run `hermes update`.", choices=choices) if raw is None or self._normalize_slash_confirm_choice(raw, choices) != "once": print(" 🟡 /update cancelled.") return False - _say_block(" ⚕ Launching update...") + _say_block(" ☤ Launching update...") # run() execs this on the main thread after prompt_toolkit restores terminal modes; # relaunching from this daemon thread would skip cleanup (POSIX) / only end the thread (Windows). self._pending_relaunch = ["update"] diff --git a/hermes_cli/cli_session_mixin.py b/hermes_cli/cli_session_mixin.py index a99a71e62d..b9ae6400e5 100644 --- a/hermes_cli/cli_session_mixin.py +++ b/hermes_cli/cli_session_mixin.py @@ -1291,9 +1291,9 @@ class CLISessionMixin: if not msg_count: try: from hermes_cli.skin_engine import get_active_goodbye - goodbye = get_active_goodbye("Goodbye! ⚕") + goodbye = get_active_goodbye("Goodbye! ☤") except Exception: - goodbye = "Goodbye! ⚕" + goodbye = "Goodbye! ☤" print(goodbye) return diff --git a/hermes_cli/cli_status_bar_mixin.py b/hermes_cli/cli_status_bar_mixin.py index 1e9a7c7076..cbac7c56d4 100644 --- a/hermes_cli/cli_status_bar_mixin.py +++ b/hermes_cli/cli_status_bar_mixin.py @@ -1001,9 +1001,9 @@ class CLIStatusBarMixin: if _ok("model"): if styled: - segs.append([(_SB, " ⚕ "), (_STRONG, model_short)]) + segs.append([(_SB, " ☤ "), (_STRONG, model_short)]) else: - segs.append([("", f"⚕ {model_short}")]) + segs.append([("", f"☤ {model_short}")]) narrow, wide = width < 52, width >= 76 if narrow: # Narrow bars put duration ahead of the goal segment; the other tiers reverse it. @@ -1074,7 +1074,7 @@ class CLIStatusBarMixin: session_title = (snapshot.get("session_title") or "") if show_title else "" segs = self._status_bar_segments( snapshot, width, field_set, self._is_session_yolo_active(), styled=False) - parts = ["".join(t for _, t in seg) for seg in segs] or [f"⚕ {model_short}"] + parts = ["".join(t for _, t in seg) for seg in segs] or [f"☤ {model_short}"] # Narrow bars always join the battery with │; wider tiers use the tier separator. if battery_label: parts.insert(0, battery_label) @@ -1084,7 +1084,7 @@ class CLIStatusBarMixin: text = (" · " if width < 76 else " │ ").join(parts) return self._right_align_status_title(text, session_title, width) except Exception: - return f"⚕ {self.model if getattr(self, 'model', None) else 'Hermes'}" + return f"☤ {self.model if getattr(self, 'model', None) else 'Hermes'}" def _get_status_bar_fragments(self): if ( @@ -1107,7 +1107,7 @@ class CLIStatusBarMixin: snapshot, width, field_set, self._is_session_yolo_active(), styled=True) sep = " · " if width < 76 else " │ " frags: list = [] - for seg in segs or [[(_SB, " ⚕ "), (_STRONG, snapshot["model_short"])]]: + for seg in segs or [[(_SB, " ☤ "), (_STRONG, snapshot["model_short"])]]: if frags: frags.append((_DIM, sep)) frags.extend(seg) @@ -1120,7 +1120,7 @@ class CLIStatusBarMixin: if stash_indicator and _ok("stash"): frags.extend([(_DIM, " · "), (_STRONG, stash_indicator)]) frags.append((_SB, " ")) # one-cell right margin - # Battery is the first element when enabled: prepend ahead of the ⚕ marker. + # Battery is the first element when enabled: prepend ahead of the ☤ marker. battery_label = snapshot.get("battery_label") or "" if battery_label and _ok("battery"): battery_style = self._battery_status_style(snapshot.get("battery_category", "dim")) diff --git a/hermes_cli/cli_stream_mixin.py b/hermes_cli/cli_stream_mixin.py index ba12ac6223..9e847a6375 100644 --- a/hermes_cli/cli_stream_mixin.py +++ b/hermes_cli/cli_stream_mixin.py @@ -423,10 +423,10 @@ class CLIStreamMixin: try: from hermes_cli.skin_engine import get_active_skin _skin = get_active_skin() - label = _skin.get_branding("response_label", "⚕ Hermes") + label = _skin.get_branding("response_label", "☤ Hermes") _text_hex = _skin.get_color("banner_text", "#FFF8DC") except Exception: - label = "⚕ Hermes" + label = "☤ Hermes" _text_hex = "#FFF8DC" try: # true-color escape so streamed text matches the Rich Panel appearance _r, _g, _b = (int(_text_hex[i:i + 2], 16) for i in (1, 3, 5)) diff --git a/hermes_cli/cli_tui_mixin.py b/hermes_cli/cli_tui_mixin.py index 6c23d47858..dd57ed572f 100644 --- a/hermes_cli/cli_tui_mixin.py +++ b/hermes_cli/cli_tui_mixin.py @@ -299,7 +299,7 @@ class CLITuiMixin: if self._command_running: return _state_fragment("class:prompt-working", self._command_spinner_frame()) if self._agent_running: - return _state_fragment("class:prompt-working", "⚕") + return _state_fragment("class:prompt-working", "☤") if self._voice_mode: return _state_fragment("class:voice-prompt", "🎤") return [("class:prompt", symbol)] diff --git a/hermes_cli/config.py b/hermes_cli/config.py index 6f9a67a62a..16ae90b4e4 100644 --- a/hermes_cli/config.py +++ b/hermes_cli/config.py @@ -2884,7 +2884,7 @@ def show_config(): print() print(color("┌─────────────────────────────────────────────────────────┐", Colors.CYAN)) - print(color("│ ⚕ Hermes Configuration │", Colors.CYAN)) + print(color("│ ☤ Hermes Configuration │", Colors.CYAN)) print(color("└─────────────────────────────────────────────────────────┘", Colors.CYAN)) _show_managed_banner() diff --git a/hermes_cli/config_defaults.py b/hermes_cli/config_defaults.py index ea5bdac14f..1cc1ea6ef5 100644 --- a/hermes_cli/config_defaults.py +++ b/hermes_cli/config_defaults.py @@ -1493,7 +1493,7 @@ DEFAULT_CONFIG = { }, "whatsapp": { - # reply_prefix: None = built-in "⚕ *Hermes Agent*" header; "" disables; \n allowed. + # reply_prefix: None = built-in "☤ *Hermes Agent*" header; "" disables; \n allowed. }, "telegram": { diff --git a/hermes_cli/gateway.py b/hermes_cli/gateway.py index 421180eb33..fbb1dbba37 100644 --- a/hermes_cli/gateway.py +++ b/hermes_cli/gateway.py @@ -4743,7 +4743,7 @@ def run_gateway(verbose: int = 0, quiet: bool = False, replace: bool = False, fo from gateway.run import start_gateway print("┌─────────────────────────────────────────────────────────┐") - print("│ ⚕ Hermes Gateway Starting... │") + print("│ ☤ Hermes Gateway Starting... │") print("├─────────────────────────────────────────────────────────┤") print("│ Messaging platforms + cron scheduler │") print("│ Press Ctrl+C to stop │") @@ -5650,7 +5650,7 @@ def _setup_service_action( _WIZARD_BANNER = ( "┌─────────────────────────────────────────────────────────┐", - "│ ⚕ Gateway Setup │", + "│ ☤ Gateway Setup │", "├─────────────────────────────────────────────────────────┤", "│ Configure messaging platforms and the gateway service. │", "│ Press Ctrl+C at any time to exit. │", diff --git a/hermes_cli/main_platform_setup.py b/hermes_cli/main_platform_setup.py index 7e737d6dd2..c00d8004ab 100644 --- a/hermes_cli/main_platform_setup.py +++ b/hermes_cli/main_platform_setup.py @@ -128,7 +128,7 @@ def cmd_whatsapp(args): _require_tty("whatsapp") from hermes_cli.config import get_env_value, save_env_value from hermes_constants import find_node_executable, with_hermes_node_path - _say("", "⚕ WhatsApp Setup", "=" * 50) + _say("", "☤ WhatsApp Setup", "=" * 50) wa_mode = _whatsapp_choose_mode(get_env_value, save_env_value) if wa_mode is None: @@ -192,12 +192,12 @@ def cmd_whatsapp(args): _say(" Next steps:", " 1. Start the gateway: hermes gateway", " 2. Send a message to the bot's WhatsApp number", " 3. The agent will reply automatically", "", - " Tip: Agent responses are prefixed with '⚕ Hermes Agent'") + " Tip: Agent responses are prefixed with '☤ Hermes Agent'") else: _say(" Next steps:", " 1. Start the gateway: hermes gateway", " 2. Open WhatsApp → Message Yourself", " 3. Type a message — the agent will reply", "", - " Tip: Agent responses are prefixed with '⚕ Hermes Agent'", + " Tip: Agent responses are prefixed with '☤ Hermes Agent'", " so you can tell them apart from your own messages.") _say("", " Or install as a service: hermes gateway install") diff --git a/hermes_cli/main_tui_launch.py b/hermes_cli/main_tui_launch.py index 1e51f54c41..d04f8a33a7 100644 --- a/hermes_cli/main_tui_launch.py +++ b/hermes_cli/main_tui_launch.py @@ -815,7 +815,7 @@ def _launch_tui( # preserve_inherited=False keeps --tui and other flags out of the subcommand. if code == 42: from hermes_cli.relaunch import relaunch - print("\n⚕ Launching update...\n") + print("\n☤ Launching update...\n") relaunch(["update"], preserve_inherited=False) sys.exit(code) diff --git a/hermes_cli/setup.py b/hermes_cli/setup.py index 712b298bc4..6d89bb4ad1 100644 --- a/hermes_cli/setup.py +++ b/hermes_cli/setup.py @@ -80,7 +80,7 @@ def is_interactive_stdin() -> bool: def print_noninteractive_setup_guidance(reason: str | None = None) -> None: """Print guidance for headless/non-interactive setup flows.""" print() - print(color("⚕ Hermes Setup — Non-interactive mode", Colors.CYAN, Colors.BOLD)) + print(color("☤ Hermes Setup — Non-interactive mode", Colors.CYAN, Colors.BOLD)) print() if reason: print_info(reason) @@ -588,7 +588,7 @@ def _run_setup_section(config: dict, section: str) -> None: print_info(f"Available sections: {', '.join(k for k, _, _ in SETUP_SECTIONS)}") return label, func = entry - _print_banner(f"│ ⚕ Hermes Setup — {label:<34s} │") + _print_banner(f"│ ☤ Hermes Setup — {label:<34s} │") _run_setup_steps([(label, lambda: func(config))]) save_config(config) print() @@ -679,7 +679,7 @@ def _run_setup_wizard_impl(args): from hermes_cli.auth import get_active_provider is_existing = bool(get_env_value("OPENROUTER_API_KEY") or get_env_value("OPENAI_BASE_URL") or get_active_provider() is not None) - _print_banner("│ ⚕ Hermes Agent Setup Wizard │", + _print_banner("│ ☤ Hermes Agent Setup Wizard │", "├─────────────────────────────────────────────────────────┤", "│ Let's configure your Hermes Agent installation. │", "│ Press Ctrl+C at any time to exit. │") diff --git a/hermes_cli/setup_quick.py b/hermes_cli/setup_quick.py index 5f31223aa1..0b0f4623ea 100644 --- a/hermes_cli/setup_quick.py +++ b/hermes_cli/setup_quick.py @@ -57,7 +57,7 @@ def _run_nous_flow(config: dict, *, context: str, cancel_exc: tuple, cancel_line def _run_portal_one_shot(config: dict) -> None: """One-shot Nous Portal setup (``hermes setup --portal`` / ``hermes portal``).""" from hermes_cli.setup import _info, _print_banner, print_error, print_info, print_success - _print_banner("│ ⚕ Hermes Setup — Nous Portal (one-shot) │") + _print_banner("│ ☤ Hermes Setup — Nous Portal (one-shot) │") _info(None, " One subscription, 300+ models, plus the Tool Gateway:", " web search, image generation, TTS, browser automation", " — all routed through your Nous Portal sub.", None, diff --git a/hermes_cli/setup_whatsapp_cloud.py b/hermes_cli/setup_whatsapp_cloud.py index 44750bd9f5..b507a9121d 100644 --- a/hermes_cli/setup_whatsapp_cloud.py +++ b/hermes_cli/setup_whatsapp_cloud.py @@ -293,7 +293,7 @@ def _step_allowlist() -> None: def run_whatsapp_cloud_setup() -> int: """Interactive wizard for the WhatsApp Cloud API adapter. Returns 0 on success, 1 on abort.""" _lines( - "", "⚕ WhatsApp Business Cloud API Setup", "=" * 50, "", + "", "☤ WhatsApp Business Cloud API Setup", "=" * 50, "", "This wizard configures Hermes to talk to WhatsApp via Meta's", "official Cloud API. It's the production-grade path:", "", " • No QR codes, no Node.js bridge subprocess", diff --git a/hermes_cli/skin_engine.py b/hermes_cli/skin_engine.py index 4ee2576c71..76b1cd2b79 100644 --- a/hermes_cli/skin_engine.py +++ b/hermes_cli/skin_engine.py @@ -57,7 +57,7 @@ def _wings(*glyphs) -> List[List[str]]: # Branding shared by every Hermes-named built-in (mono/daylight override help_header). _HERMES_BRANDING: Dict[str, str] = _branding( - "Hermes", "⚕", "Goodbye! ⚕", prompt="❯", help_header="(^_^)? Available Commands") + "Hermes", "☤", "Goodbye! ☤", prompt="❯", help_header="(^_^)? Available Commands") _BUILTIN_SKINS: Dict[str, Dict[str, Any]] = { "default": { @@ -489,7 +489,7 @@ def get_active_help_header(fallback: str = "(^_^)? Available Commands") -> str: return _active_branding("help_header", fallback) -def get_active_goodbye(fallback: str = "Goodbye! ⚕") -> str: +def get_active_goodbye(fallback: str = "Goodbye! ☤") -> str: return _active_branding("goodbye", fallback) diff --git a/hermes_cli/status.py b/hermes_cli/status.py index 20bb7b70d0..f588cb2e31 100644 --- a/hermes_cli/status.py +++ b/hermes_cli/status.py @@ -137,7 +137,7 @@ def _banner(lines, *styles) -> None: def _render_header(ctx): _banner(("┌─────────────────────────────────────────────────────────┐", - "│ ⚕ Hermes Agent Status │", + "│ ☤ Hermes Agent Status │", "└─────────────────────────────────────────────────────────┘"), Colors.CYAN) paused = _estop_status_line() if paused: diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py index 1bb04268a8..4241a8443f 100644 --- a/hermes_cli/tools_config.py +++ b/hermes_cli/tools_config.py @@ -917,7 +917,7 @@ def _platform_menu_label(config: dict, pkey: str) -> str: def _print_tools_summary(config: dict, enabled_platforms: List[str]) -> None: """``hermes tools --summary``: enabled toolsets per platform, non-interactive.""" total = len(_get_effective_configurable_toolsets()) - print(color("⚕ Tool Summary", Colors.CYAN, Colors.BOLD)) + print(color("☤ Tool Summary", Colors.CYAN, Colors.BOLD)) print() for pkey, enabled in _platform_toolset_summary(config, enabled_platforms).items(): print(color(f" {PLATFORMS[pkey]['label']}", Colors.BOLD) + color(f" ({len(enabled)}/{total})", Colors.DIM)) @@ -1024,7 +1024,7 @@ def tools_command(args=None, first_install: bool = False, config: dict = None): if getattr(args, "summary", False): _print_tools_summary(config, enabled_platforms) return - print(color("⚕ Hermes Tool Configuration", Colors.CYAN, Colors.BOLD)) + print(color("☤ Hermes Tool Configuration", Colors.CYAN, Colors.BOLD)) print(color(" Enable or disable tools per platform.", Colors.DIM)) print(color(" Tools that need API keys will be configured when enabled.", Colors.DIM)) print(color(" Guide: https://hermes-agent.nousresearch.com/docs/user-guide/features/tools", Colors.DIM)) diff --git a/hermes_cli/uninstall.py b/hermes_cli/uninstall.py index ba54931224..719fbeffd4 100644 --- a/hermes_cli/uninstall.py +++ b/hermes_cli/uninstall.py @@ -425,7 +425,7 @@ def run_gui_uninstall(args): skip_confirm = bool(getattr(args, "yes", False)) print() - _print_box("│ ⚕ Hermes Chat GUI Uninstaller │", Colors.MAGENTA) + _print_box("│ ☤ Hermes Chat GUI Uninstaller │", Colors.MAGENTA) print() if not summary["gui_installed"]: @@ -489,7 +489,7 @@ def run_uninstall(args): return print() - _print_box("│ ⚕ Hermes Agent Uninstaller │", Colors.MAGENTA) + _print_box("│ ☤ Hermes Agent Uninstaller │", Colors.MAGENTA) print() # Show what will be affected @@ -697,7 +697,7 @@ def _perform_uninstall( for line, col in _RELOAD_HINT[windows]: print(color(line, col) if col else line) print() - print("Thank you for using Hermes Agent! ⚕") + print("Thank you for using Hermes Agent! ☤") print() diff --git a/hermes_cli/update_cmd.py b/hermes_cli/update_cmd.py index d55cf9481a..758b5c7a8e 100644 --- a/hermes_cli/update_cmd.py +++ b/hermes_cli/update_cmd.py @@ -588,9 +588,9 @@ def _print_update_check_result(behind: int | None, compare_branch: str) -> None: print("✓ Already up to date.") return if behind is not None: - print(f"⚕ Update available: {behind} {'commit' if behind == 1 else 'commits'} behind {compare_branch}.") + print(f"☤ Update available: {behind} {'commit' if behind == 1 else 'commits'} behind {compare_branch}.") else: - print(f"⚕ Update available (behind {compare_branch}).") + print(f"☤ Update available (behind {compare_branch}).") from hermes_cli.config import recommended_update_command print(f" Run '{recommended_update_command()}' to install.") @@ -1282,7 +1282,7 @@ def _cmd_update_impl(args, gateway_mode: bool): opts = _resolve_update_options(args, gateway_mode) gw_input_fn, assume_yes = opts.gw_input_fn, opts.assume_yes - print("⚕ Updating Hermes Agent...") + print("☤ Updating Hermes Agent...") print() _pre_update_plan = _begin_update_receipt_and_plan(args) diff --git a/locales/af.yaml b/locales/af.yaml index 6e5376ae62..61e30a9600 100644 --- a/locales/af.yaml +++ b/locales/af.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Nie 'n git-bewaarplek nie — kan nie opdateer nie." hermes_cmd_not_found: "✗ Kon nie die `hermes`-opdrag vind nie. Hermes loop, maar die opdateeropdrag kon nie die uitvoerbare lêer op PATH of via die huidige Python-vertolker vind nie. Probeer `hermes update` met die hand in jou terminale uitvoer." start_failed: "✗ Kon nie opdatering begin nie: {error}" - starting: "⚕ Begin Hermes-opdatering… Ek sal vordering hier stroom." + starting: "☤ Begin Hermes-opdatering… Ek sal vordering hier stroom." usage: rate_limits: "⏱️ **Tariefperke:** {state}" diff --git a/locales/ar.yaml b/locales/ar.yaml index ce9bc2663f..ea1eaee8fc 100644 --- a/locales/ar.yaml +++ b/locales/ar.yaml @@ -389,7 +389,7 @@ gateway: not_git_repo: "✗ ليس مستودع git — لا يمكن التحديث." hermes_cmd_not_found: "✗ تعذّر تحديد موقع أمر `hermes`. Hermes يعمل، لكن أمر التحديث لم يجد الملف التنفيذي على PATH أو عبر مُفسّر Python الحالي. جرّب تشغيل `hermes update` يدويًا في طرفيتك." start_failed: "✗ فشل بدء التحديث: {error}" - starting: "⚕ جارٍ بدء تحديث Hermes… سأبثّ التقدّم هنا." + starting: "☤ جارٍ بدء تحديث Hermes… سأبثّ التقدّم هنا." usage: rate_limits: "⏱️ **حدود المعدّل:** {state}" diff --git a/locales/de.yaml b/locales/de.yaml index 0259e786fa..93e1cd0311 100644 --- a/locales/de.yaml +++ b/locales/de.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Kein Git-Repository — Update nicht möglich." hermes_cmd_not_found: "✗ Der Befehl `hermes` konnte nicht gefunden werden. Hermes läuft, aber der Update-Befehl konnte das ausführbare Programm weder im PATH noch über den aktuellen Python-Interpreter finden. Versuchen Sie, `hermes update` manuell im Terminal auszuführen." start_failed: "✗ Update konnte nicht gestartet werden: {error}" - starting: "⚕ Hermes-Update wird gestartet… Ich streame den Fortschritt hier." + starting: "☤ Hermes-Update wird gestartet… Ich streame den Fortschritt hier." usage: rate_limits: "⏱️ **Ratenlimits:** {state}" diff --git a/locales/en.yaml b/locales/en.yaml index 621bfb7705..f8548e9dd2 100644 --- a/locales/en.yaml +++ b/locales/en.yaml @@ -400,7 +400,7 @@ gateway: not_git_repo: "✗ Not a git repository — cannot update." hermes_cmd_not_found: "✗ Could not locate the `hermes` command. Hermes is running, but the update command could not find the executable on PATH or via the current Python interpreter. Try running `hermes update` manually in your terminal." start_failed: "✗ Failed to start update: {error}" - starting: "⚕ Starting Hermes update… I'll stream progress here." + starting: "☤ Starting Hermes update… I'll stream progress here." usage: rate_limits: "⏱️ **Rate Limits:** {state}" diff --git a/locales/es.yaml b/locales/es.yaml index 434f1aca34..9d99e3b530 100644 --- a/locales/es.yaml +++ b/locales/es.yaml @@ -384,7 +384,7 @@ gateway: not_git_repo: "✗ No es un repositorio git — no se puede actualizar." hermes_cmd_not_found: "✗ No se pudo localizar el comando `hermes`. Hermes está en ejecución, pero el comando de actualización no encontró el ejecutable en PATH ni a través del intérprete de Python actual. Intenta ejecutar `hermes update` manualmente en tu terminal." start_failed: "✗ No se pudo iniciar la actualización: {error}" - starting: "⚕ Iniciando la actualización de Hermes… Transmitiré el progreso aquí." + starting: "☤ Iniciando la actualización de Hermes… Transmitiré el progreso aquí." usage: rate_limits: "⏱️ **Límites de tasa:** {state}" diff --git a/locales/fr.yaml b/locales/fr.yaml index 8fa2daa16a..43b2656395 100644 --- a/locales/fr.yaml +++ b/locales/fr.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Pas un dépôt git — impossible de mettre à jour." hermes_cmd_not_found: "✗ Impossible de localiser la commande `hermes`. Hermes est en cours d'exécution, mais la commande de mise à jour n'a pas pu trouver l'exécutable dans le PATH ni via l'interpréteur Python actuel. Essayez d'exécuter `hermes update` manuellement dans votre terminal." start_failed: "✗ Échec du démarrage de la mise à jour : {error}" - starting: "⚕ Démarrage de la mise à jour Hermes… Je diffuserai la progression ici." + starting: "☤ Démarrage de la mise à jour Hermes… Je diffuserai la progression ici." usage: rate_limits: "⏱️ **Limites de débit :** {state}" diff --git a/locales/ga.yaml b/locales/ga.yaml index f96570eda0..75a9430ede 100644 --- a/locales/ga.yaml +++ b/locales/ga.yaml @@ -391,7 +391,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Ní stór git é seo — ní féidir nuashonrú." hermes_cmd_not_found: "✗ Níorbh fhéidir an t-ordú `hermes` a aimsiú. Tá Hermes ag rith, ach níorbh fhéidir leis an ordú nuashonraithe an inrite a aimsiú ar PATH ná tríd an léirmhínitheoir Python reatha. Bain triail as `hermes update` a rith de láimh i do theirminéal." start_failed: "✗ Theip ar nuashonrú a thosú: {error}" - starting: "⚕ Ag tosú nuashonrú Hermes… Cuirfidh mé an dul chun cinn ar shruth anseo." + starting: "☤ Ag tosú nuashonrú Hermes… Cuirfidh mé an dul chun cinn ar shruth anseo." usage: rate_limits: "⏱️ **Teorainneacha Ráta:** {state}" diff --git a/locales/hu.yaml b/locales/hu.yaml index e26e211088..4913985b0e 100644 --- a/locales/hu.yaml +++ b/locales/hu.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Nem git-tárhely — frissítés nem lehetséges." hermes_cmd_not_found: "✗ Nem sikerült megtalálni a `hermes` parancsot. A Hermes fut, de a frissítőparancs nem találta a futtatható fájlt a PATH-on vagy a jelenlegi Python interpreteren keresztül. Próbáld futtatni a `hermes update` parancsot manuálisan a terminálban." start_failed: "✗ Nem sikerült elindítani a frissítést: {error}" - starting: "⚕ Hermes frissítés indítása… A folyamatot itt fogom közvetíteni." + starting: "☤ Hermes frissítés indítása… A folyamatot itt fogom közvetíteni." usage: rate_limits: "⏱️ **Sebességkorlátok:** {state}" diff --git a/locales/it.yaml b/locales/it.yaml index 9e1ecb6d71..24a6c2c7ae 100644 --- a/locales/it.yaml +++ b/locales/it.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Non è un repository git — impossibile aggiornare." hermes_cmd_not_found: "✗ Impossibile localizzare il comando `hermes`. Hermes è in esecuzione, ma il comando di aggiornamento non ha trovato l'eseguibile nel PATH o tramite l'interprete Python attuale. Prova a eseguire `hermes update` manualmente nel terminale." start_failed: "✗ Avvio dell'aggiornamento non riuscito: {error}" - starting: "⚕ Avvio dell'aggiornamento di Hermes… mostrerò qui i progressi in streaming." + starting: "☤ Avvio dell'aggiornamento di Hermes… mostrerò qui i progressi in streaming." usage: rate_limits: "⏱️ **Limiti di frequenza:** {state}" diff --git a/locales/ja.yaml b/locales/ja.yaml index 0819b688c2..ac80eef3d4 100644 --- a/locales/ja.yaml +++ b/locales/ja.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Git リポジトリではありません — 更新できません。" hermes_cmd_not_found: "✗ `hermes` コマンドが見つかりません。Hermes は実行中ですが、更新コマンドは PATH 上にも現在の Python インタープリタ経由でも実行可能ファイルを見つけられませんでした。ターミナルで `hermes update` を手動で実行してみてください。" start_failed: "✗ 更新の開始に失敗しました: {error}" - starting: "⚕ Hermes の更新を開始しています… 進捗をここにストリーミングします。" + starting: "☤ Hermes の更新を開始しています… 進捗をここにストリーミングします。" usage: rate_limits: "⏱️ **レート制限:** {state}" diff --git a/locales/ko.yaml b/locales/ko.yaml index 1608fcb00f..b18a9a52e2 100644 --- a/locales/ko.yaml +++ b/locales/ko.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ git 저장소가 아닙니다 — 업데이트할 수 없습니다." hermes_cmd_not_found: "✗ `hermes` 명령을 찾을 수 없습니다. Hermes는 실행 중이지만 PATH나 현재 Python 인터프리터를 통해 실행 파일을 찾을 수 없습니다. 터미널에서 `hermes update`를 직접 실행해 보세요." start_failed: "✗ 업데이트 시작 실패: {error}" - starting: "⚕ Hermes 업데이트를 시작합니다… 진행 상황을 여기에 스트리밍하겠습니다." + starting: "☤ Hermes 업데이트를 시작합니다… 진행 상황을 여기에 스트리밍하겠습니다." usage: rate_limits: "⏱️ **요청 제한:** {state}" diff --git a/locales/pt.yaml b/locales/pt.yaml index 8e0e595b4b..25575ad6f1 100644 --- a/locales/pt.yaml +++ b/locales/pt.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Não é um repositório git — não é possível atualizar." hermes_cmd_not_found: "✗ Não foi possível localizar o comando `hermes`. O Hermes está em execução, mas o comando de atualização não conseguiu encontrar o executável no PATH nem através do interpretador Python atual. Tenta executar `hermes update` manualmente no teu terminal." start_failed: "✗ Falha ao iniciar a atualização: {error}" - starting: "⚕ A iniciar a atualização do Hermes… Vou transmitir o progresso aqui." + starting: "☤ A iniciar a atualização do Hermes… Vou transmitir o progresso aqui." usage: rate_limits: "⏱️ **Limites de taxa:** {state}" diff --git a/locales/ru.yaml b/locales/ru.yaml index dc971f61f0..48636fca0a 100644 --- a/locales/ru.yaml +++ b/locales/ru.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Не git-репозиторий — обновление невозможно." hermes_cmd_not_found: "✗ Не удалось найти команду `hermes`. Hermes запущен, но команда обновления не нашла исполняемый файл в PATH или через текущий интерпретатор Python. Попробуйте выполнить `hermes update` вручную в терминале." start_failed: "✗ Не удалось запустить обновление: {error}" - starting: "⚕ Запуск обновления Hermes… Я буду транслировать прогресс сюда." + starting: "☤ Запуск обновления Hermes… Я буду транслировать прогресс сюда." usage: rate_limits: "⏱️ **Ограничения скорости:** {state}" diff --git a/locales/tr.yaml b/locales/tr.yaml index cdeba56588..bda87570ba 100644 --- a/locales/tr.yaml +++ b/locales/tr.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Git deposu değil — güncellenemiyor." hermes_cmd_not_found: "✗ `hermes` komutu bulunamadı. Hermes çalışıyor, ancak güncelleme komutu yürütülebilir dosyayı PATH'te veya mevcut Python yorumlayıcısı aracılığıyla bulamadı. Terminalde `hermes update` komutunu manuel olarak çalıştırmayı deneyin." start_failed: "✗ Güncelleme başlatılamadı: {error}" - starting: "⚕ Hermes güncellemesi başlatılıyor… İlerlemeyi buraya akıtacağım." + starting: "☤ Hermes güncellemesi başlatılıyor… İlerlemeyi buraya akıtacağım." usage: rate_limits: "⏱️ **Hız Sınırları:** {state}" diff --git a/locales/uk.yaml b/locales/uk.yaml index 1f4a9dd7b3..619307c431 100644 --- a/locales/uk.yaml +++ b/locales/uk.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ Не git-репозиторій — оновлення неможливе." hermes_cmd_not_found: "✗ Не вдалося знайти команду `hermes`. Hermes запущено, але команда оновлення не знайшла виконуваний файл у PATH або через поточний інтерпретатор Python. Спробуйте виконати `hermes update` вручну у вашому терміналі." start_failed: "✗ Не вдалося запустити оновлення: {error}" - starting: "⚕ Запуск оновлення Hermes… Я транслюватиму прогрес сюди." + starting: "☤ Запуск оновлення Hermes… Я транслюватиму прогрес сюди." usage: rate_limits: "⏱️ **Обмеження швидкості:** {state}" diff --git a/locales/zh-hant.yaml b/locales/zh-hant.yaml index 0ae999885c..ff57107f80 100644 --- a/locales/zh-hant.yaml +++ b/locales/zh-hant.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ 不是 git 儲存庫 — 無法更新。" hermes_cmd_not_found: "✗ 找不到 `hermes` 指令。Hermes 正在執行,但更新指令無法在 PATH 上或透過目前的 Python 解譯器找到執行檔。請嘗試在終端機中手動執行 `hermes update`。" start_failed: "✗ 啟動更新失敗:{error}" - starting: "⚕ 正在啟動 Hermes 更新…… 進度將在此處顯示。" + starting: "☤ 正在啟動 Hermes 更新…… 進度將在此處顯示。" usage: rate_limits: "⏱️ **速率限制:** {state}" diff --git a/locales/zh.yaml b/locales/zh.yaml index 5ef9fd0612..6364ae8fa8 100644 --- a/locales/zh.yaml +++ b/locales/zh.yaml @@ -387,7 +387,7 @@ Future messages in this room will use that transcript until `/reset` or another not_git_repo: "✗ 不是 git 仓库 — 无法更新。" hermes_cmd_not_found: "✗ 无法找到 `hermes` 命令。Hermes 正在运行,但更新命令无法在 PATH 上或通过当前 Python 解释器找到可执行文件。请尝试在终端中手动运行 `hermes update`。" start_failed: "✗ 启动更新失败:{error}" - starting: "⚕ 正在启动 Hermes 更新…… 进度将在此处显示。" + starting: "☤ 正在启动 Hermes 更新…… 进度将在此处显示。" usage: rate_limits: "⏱️ **速率限制:** {state}" diff --git a/plugins/platforms/discord/adapter.py b/plugins/platforms/discord/adapter.py index 817849d6ae..0d5611fd8e 100644 --- a/plugins/platforms/discord/adapter.py +++ b/plugins/platforms/discord/adapter.py @@ -5367,13 +5367,13 @@ class DiscordAdapter(DiscordMediaMixin, BasePlatformAdapter): def _build(_channel): default_hint = f" (default: {default})" if default else "" embed = discord.Embed( - title="⚕ Update Needs Your Input", description=f"{prompt}{default_hint}", color=discord.Color.gold(), + title="☤ Update Needs Your Input", description=f"{prompt}{default_hint}", color=discord.Color.gold(), ) view = UpdatePromptView( session_key=session_key, allowed_user_ids=self._allowed_user_ids, allowed_role_ids=self._allowed_role_ids, ) - content = self._self_contained_prompt_content("⚕ **Update Needs Your Input**", f"{prompt}{default_hint}") + content = self._self_contained_prompt_content("☤ **Update Needs Your Input**", f"{prompt}{default_hint}") return {"content": content, "embed": embed, "view": view}, view result = await self._send_prompt(chat_id, metadata, _build) if result.success and _metadata_marks_nonconversational(metadata): diff --git a/plugins/platforms/feishu/adapter.py b/plugins/platforms/feishu/adapter.py index fbe595a175..166249b741 100644 --- a/plugins/platforms/feishu/adapter.py +++ b/plugins/platforms/feishu/adapter.py @@ -1706,7 +1706,7 @@ class FeishuAdapter(BasePlatformAdapter): return _card_button(label, btn_type, {"hermes_update_prompt_action": answer, "update_prompt_id": prompt_id}) actions = [_btn("✓ Yes", "y", "primary"), _btn("✗ No", "n", "danger")] - return _card("⚕ Update Needs Your Input", "orange", f"{prompt}{default_hint}", actions=actions) + return _card("☤ Update Needs Your Input", "orange", f"{prompt}{default_hint}", actions=actions) async def send_update_prompt( self, chat_id: str, prompt: str, default: str = "", session_key: str = "", diff --git a/plugins/platforms/telegram/adapter.py b/plugins/platforms/telegram/adapter.py index 0085982926..c4c644c182 100644 --- a/plugins/platforms/telegram/adapter.py +++ b/plugins/platforms/telegram/adapter.py @@ -3781,7 +3781,7 @@ class TelegramAdapter(BasePlatformAdapter): """Send an inline-keyboard Yes/No prompt for the gateway ``/update`` watcher.""" def build(): default_hint = f" (default: {default})" if default else "" - text = self.format_message(f"⚕ *Update needs your input:*\n\n{prompt}{default_hint}") + text = self.format_message(f"☤ *Update needs your input:*\n\n{prompt}{default_hint}") keyboard = InlineKeyboardMarkup([[ InlineKeyboardButton("✓ Yes", callback_data="update_prompt:y"), InlineKeyboardButton("✗ No", callback_data="update_prompt:n")]]) @@ -4439,7 +4439,7 @@ class TelegramAdapter(BasePlatformAdapter): if not await self._callback_authorized(query, cb, "⛔ You are not authorized to answer update prompts."): return await query.answer(text=f"Sent '{answer}' to the update process.") - await self._edit_md_quiet(query, f"⚕ Update prompt answered: *{'Yes' if answer == 'y' else 'No'}*") + await self._edit_md_quiet(query, f"☤ Update prompt answered: *{'Yes' if answer == 'y' else 'No'}*") try: from hermes_constants import get_hermes_home response_path = get_hermes_home() / ".update_response" diff --git a/tests/hermes_cli/test_ensure_utf8_locale.py b/tests/hermes_cli/test_ensure_utf8_locale.py index be8ad461bc..574d0ec33b 100644 --- a/tests/hermes_cli/test_ensure_utf8_locale.py +++ b/tests/hermes_cli/test_ensure_utf8_locale.py @@ -1,7 +1,7 @@ """Regression tests for hermes_cli._ensure_utf8(). Covers the crash class where the setup wizard (and other banner-printing -commands) emit box-drawing characters and the ⚕ glyph, which raise +commands) emit box-drawing characters and the ☤ glyph, which raise UnicodeEncodeError when stdout/stderr are bound to a non-UTF-8 codec. Historically the repair was gated on ``sys.platform == "win32"`` and only @@ -19,7 +19,7 @@ import hermes_cli # The exact glyphs the setup wizard / banners print (setup.py ~line 2962+). -_BANNER = "┌─────┐\n│ ⚕ Hermes │\n└─────┘" +_BANNER = "┌─────┐\n│ ☤ Hermes │\n└─────┘" class _FakeStream: @@ -109,7 +109,7 @@ def test_fallback_when_reconfigure_unavailable(monkeypatch, tmp_path): sys.stdout.write(_BANNER) sys.stdout.flush() fh.close() - assert "⚕".encode("utf-8") in real_path.read_bytes() + assert "☤".encode("utf-8") in real_path.read_bytes() diff --git a/tests/run_agent/test_unicode_ascii_codec.py b/tests/run_agent/test_unicode_ascii_codec.py index d9f94f4623..a053768f04 100644 --- a/tests/run_agent/test_unicode_ascii_codec.py +++ b/tests/run_agent/test_unicode_ascii_codec.py @@ -72,14 +72,14 @@ class TestSurrogateVsAsciiSanitization: def test_ascii_codec_strips_all_non_ascii(self): """ASCII codec case: all non-ASCII is stripped, not replaced.""" - messages = [{"role": "user", "content": "test ⚕🤖你好 end"}] + messages = [{"role": "user", "content": "test ☤🤖你好 end"}] assert _sanitize_messages_non_ascii(messages) is True # All non-ASCII chars removed; spaces around them collapse assert messages[0]["content"] == "test end" def test_no_surrogates_returns_false(self): """When no surrogates present, _sanitize_messages_surrogates returns False.""" - messages = [{"role": "user", "content": "hello ⚕ world"}] + messages = [{"role": "user", "content": "hello ☤ world"}] assert _sanitize_messages_surrogates(messages) is False diff --git a/ui-tui/src/components/appChrome.tsx b/ui-tui/src/components/appChrome.tsx index 709a484d68..fd7ba38dce 100644 --- a/ui-tui/src/components/appChrome.tsx +++ b/ui-tui/src/components/appChrome.tsx @@ -30,7 +30,7 @@ export const padVerb = (verb: string) => `${verb}…`.padEnd(VERB_PAD_LEN, ' ') // Compact alternates for the `emoji` and `ascii` indicator styles. // Each entry is a fixed-width (display-width) glyph. -const EMOJI_FRAMES = ['⚕ ', '🌀', '🤔', '✨', '🍵', '🔮'] +const EMOJI_FRAMES = ['☤ ', '🌀', '🤔', '✨', '🍵', '🔮'] const ASCII_FRAMES = ['|', '/', '-', '\\'] // Faster tick for spinner-style indicators — they read as motion only @@ -54,7 +54,7 @@ const renderIndicator = (style: IndicatorStyle, tick: number): IndicatorRender = if (style === 'emoji') { return { - frame: EMOJI_FRAMES[tick % EMOJI_FRAMES.length] ?? '⚕ ', + frame: EMOJI_FRAMES[tick % EMOJI_FRAMES.length] ?? '☤ ', intervalMs: SPINNER_TICK_MS * 6, showVerb: true } diff --git a/ui-tui/src/components/appLayout.tsx b/ui-tui/src/components/appLayout.tsx index cad8caf42a..d05e60fb50 100644 --- a/ui-tui/src/components/appLayout.tsx +++ b/ui-tui/src/components/appLayout.tsx @@ -451,7 +451,7 @@ const ComposerPane = memo(function ComposerPane({ )} - {!composer.empty && !ui.sid && ⚕ {ui.status}} + {!composer.empty && !ui.sid && ☤ {ui.status}} diff --git a/ui-tui/src/theme.ts b/ui-tui/src/theme.ts index 11ef941315..3601c8634d 100644 --- a/ui-tui/src/theme.ts +++ b/ui-tui/src/theme.ts @@ -251,10 +251,10 @@ export function themeToneHex(tone: string): string { const BRAND: ThemeBrand = { name: 'Hermes Agent', - icon: '⚕', + icon: '☤', prompt: '❯', welcome: 'Type your message or /help for commands.', - goodbye: 'Goodbye! ⚕', + goodbye: 'Goodbye! ☤', tool: '┊', helpHeader: '(^_^)? Commands' } diff --git a/website/docs/reference/cli-symbols.md b/website/docs/reference/cli-symbols.md index c3487f8e39..76d0fcd513 100644 --- a/website/docs/reference/cli-symbols.md +++ b/website/docs/reference/cli-symbols.md @@ -37,7 +37,7 @@ The single line at the bottom of the TUI. Segments appear only when relevant and | Symbol | Meaning | |--------|---------| | `⠋⠙⠹…` (braille patterns) | Busy spinner. Thinking and tool phases use different braille animation sets. | -| `⚕ 🌀 🤔 ✨ 🍵 🔮` | Frames of the `emoji` busy-indicator style (`/indicator emoji`). The default style rotates kaomoji faces instead. | +| `☤ 🌀 🤔 ✨ 🍵 🔮` | Frames of the `emoji` busy-indicator style (`/indicator emoji`). The default style rotates kaomoji faces instead. | | | / - \ | Frames of the `ascii` busy-indicator style. | | `⏱` | Per-prompt elapsed time while the turn runs, e.g. `⏱ 12s/3m 45s` (turn time / session time). | | `⏲` | The same timer, frozen after the turn completes. | diff --git a/website/docs/user-guide/cli.md b/website/docs/user-guide/cli.md index 7887e61a1e..6c4ed6526a 100644 --- a/website/docs/user-guide/cli.md +++ b/website/docs/user-guide/cli.md @@ -137,7 +137,7 @@ The welcome banner shows your model, terminal backend, working directory, availa A persistent status bar sits above the input area, updating in real time: ``` - ⚕ claude-sonnet-4-20250514 │ 12.4K/200K │ [██████░░░░] 6% │ $0.06 │ 15m + ☤ claude-sonnet-4-20250514 │ 12.4K/200K │ [██████░░░░] 6% │ $0.06 │ 15m ``` | Element | Description | @@ -529,7 +529,7 @@ Each `/bg` prompt spawns a **completely separate agent session** in a daemon thr When a background task finishes, the result appears as a panel in your terminal: ``` -╭─ ⚕ Hermes (background #1) ──────────────────────────────────╮ +╭─ ☤ Hermes (background #1) ──────────────────────────────────╮ │ Found 3 errors in syslog from today: │ │ 1. OOM killer invoked at 03:22 — killed process nginx │ │ 2. Disk I/O error on /dev/sda1 at 07:15 │ diff --git a/website/docs/user-guide/features/skins.md b/website/docs/user-guide/features/skins.md index 75353479f1..d4841eb699 100644 --- a/website/docs/user-guide/features/skins.md +++ b/website/docs/user-guide/features/skins.md @@ -94,8 +94,8 @@ Text strings used throughout the CLI interface. |-----|-------------|---------| | `agent_name` | Name shown in banner title and status display | `Hermes Agent` | | `welcome` | Welcome message shown at CLI startup | `Welcome to Hermes Agent! Type your message or /help for commands.` | -| `goodbye` | Message shown on exit | `Goodbye! ⚕` | -| `response_label` | Label on the response box header | ` ⚕ Hermes ` | +| `goodbye` | Message shown on exit | `Goodbye! ☤` | +| `response_label` | Label on the response box header | ` ☤ Hermes ` | | `prompt_symbol` | Symbol before the user input prompt (bare token, renderers add a trailing space) | `❯` | | `help_header` | Header text for the `/help` command output | `(^_^)? Available Commands` | diff --git a/website/docs/user-guide/messaging/whatsapp.md b/website/docs/user-guide/messaging/whatsapp.md index b307747a09..7fb088085f 100644 --- a/website/docs/user-guide/messaging/whatsapp.md +++ b/website/docs/user-guide/messaging/whatsapp.md @@ -173,7 +173,7 @@ Hermes supports voice on WhatsApp: - **Incoming:** Voice messages (`.ogg` opus) are automatically transcribed using the configured STT provider: local `faster-whisper`, Groq Whisper (`GROQ_API_KEY`), or OpenAI Whisper (`VOICE_TOOLS_OPENAI_KEY`) - **Outgoing:** TTS responses are sent as MP3 audio file attachments -- Agent responses are prefixed with "⚕ **Hermes Agent**" by default. You can customize or disable this in `config.yaml`: +- Agent responses are prefixed with "☤ **Hermes Agent**" by default. You can customize or disable this in `config.yaml`: ```yaml # ~/.hermes/config.yaml diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/cli.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/cli.md index 6ff9cb00a0..f08c16ce4e 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/cli.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/cli.md @@ -59,7 +59,7 @@ hermes -w -z "Fix issue #123" # 在 worktree 中以单次查询模式运行 一个持久状态栏位于输入区域上方,实时更新: ``` - ⚕ claude-sonnet-4-20250514 │ 12.4K/200K │ [██████░░░░] 6% │ $0.06 │ 15m + ☤ claude-sonnet-4-20250514 │ 12.4K/200K │ [██████░░░░] 6% │ $0.06 │ 15m ``` | 元素 | 描述 | @@ -412,7 +412,7 @@ Hermes 立即确认任务并将提示符还给你: 后台任务完成时,结果会以面板形式出现在终端中: ``` -╭─ ⚕ Hermes (background #1) ──────────────────────────────────╮ +╭─ ☤ Hermes (background #1) ──────────────────────────────────╮ │ Found 3 errors in syslog from today: │ │ 1. OOM killer invoked at 03:22 — killed process nginx │ │ 2. Disk I/O error on /dev/sda1 at 07:15 │ diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/skins.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/skins.md index f4cfe893b9..1067e01537 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/skins.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/skins.md @@ -94,8 +94,8 @@ CLI 界面中使用的文字字符串。 |----|------|--------| | `agent_name` | 横幅标题和状态显示中的名称 | `Hermes Agent` | | `welcome` | CLI 启动时显示的欢迎消息 | `Welcome to Hermes Agent! Type your message or /help for commands.` | -| `goodbye` | 退出时显示的消息 | `Goodbye! ⚕` | -| `response_label` | 响应框标题上的标签 | ` ⚕ Hermes ` | +| `goodbye` | 退出时显示的消息 | `Goodbye! ☤` | +| `response_label` | 响应框标题上的标签 | ` ☤ Hermes ` | | `prompt_symbol` | 用户输入 prompt 前的符号(裸 token,渲染器会在后面添加空格) | `❯` | | `help_header` | `/help` 命令输出的标题文字 | `(^_^)? Available Commands` | diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/messaging/whatsapp.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/messaging/whatsapp.md index 9e9ac40049..87c63d194c 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/messaging/whatsapp.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/messaging/whatsapp.md @@ -160,7 +160,7 @@ Hermes 支持 WhatsApp 上的语音功能: - **接收:** 语音消息(`.ogg` opus 格式)会使用已配置的 STT 提供商自动转录:本地 `faster-whisper`、Groq Whisper(`GROQ_API_KEY`)或 OpenAI Whisper(`VOICE_TOOLS_OPENAI_KEY`) - **发送:** TTS 响应以 MP3 音频文件附件形式发送 -- Agent 响应默认以"⚕ **Hermes Agent**"为前缀。可在 `config.yaml` 中自定义或禁用: +- Agent 响应默认以"☤ **Hermes Agent**"为前缀。可在 `config.yaml` 中自定义或禁用: ```yaml # ~/.hermes/config.yaml