diff --git a/gateway/run.py b/gateway/run.py index 94381d8be..f0320ef61 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -6586,6 +6586,11 @@ class GatewayRunner: import asyncio as _asyncio args = event.get_command_args().strip() + + # Normalize Unicode dashes (Telegram/iOS auto-converts -- to em/en dash) + import re as _re + args = _re.sub(r'[\u2012\u2013\u2014\u2015](days|source)', r'--\1', args) + days = 30 source = None diff --git a/hermes_cli/model_switch.py b/hermes_cli/model_switch.py index dee0cb23d..11c2fa06a 100644 --- a/hermes_cli/model_switch.py +++ b/hermes_cli/model_switch.py @@ -274,6 +274,11 @@ def parse_model_flags(raw_args: str) -> tuple[str, str, bool]: is_global = False explicit_provider = "" + # Normalize Unicode dashes (Telegram/iOS auto-converts -- to em/en dash) + # A single Unicode dash before a flag keyword becomes "--" + import re as _re + raw_args = _re.sub(r'[\u2012\u2013\u2014\u2015](provider|global)', r'--\1', raw_args) + # Extract --global if "--global" in raw_args: is_global = True diff --git a/tests/gateway/test_insights_unicode_flags.py b/tests/gateway/test_insights_unicode_flags.py new file mode 100644 index 000000000..28e9a2378 --- /dev/null +++ b/tests/gateway/test_insights_unicode_flags.py @@ -0,0 +1,54 @@ +"""Tests for Unicode dash normalization in /insights command flag parsing. + +Telegram on iOS auto-converts -- to em/en dashes. The /insights handler +normalizes these before parsing --days and --source flags. +""" +import re +import pytest + + +# The regex from gateway/run.py insights handler +_UNICODE_DASH_RE = re.compile(r'[\u2012\u2013\u2014\u2015](days|source)') + + +def _normalize_insights_args(raw: str) -> str: + """Apply the same normalization as the /insights handler.""" + return _UNICODE_DASH_RE.sub(r'--\1', raw) + + +class TestInsightsUnicodeDashFlags: + """--days and --source must survive iOS Unicode dash conversion.""" + + @pytest.mark.parametrize("input_str,expected", [ + # Standard double hyphen (baseline) + ("--days 7", "--days 7"), + ("--source telegram", "--source telegram"), + # Em dash (U+2014) + ("\u2014days 7", "--days 7"), + ("\u2014source telegram", "--source telegram"), + # En dash (U+2013) + ("\u2013days 7", "--days 7"), + ("\u2013source telegram", "--source telegram"), + # Figure dash (U+2012) + ("\u2012days 7", "--days 7"), + # Horizontal bar (U+2015) + ("\u2015days 7", "--days 7"), + # Combined flags with em dashes + ("\u2014days 30 \u2014source cli", "--days 30 --source cli"), + ]) + def test_unicode_dash_normalized(self, input_str, expected): + result = _normalize_insights_args(input_str) + assert result == expected + + def test_regular_hyphens_unaffected(self): + """Normal --days/--source must pass through unchanged.""" + assert _normalize_insights_args("--days 7 --source discord") == "--days 7 --source discord" + + def test_bare_number_still_works(self): + """Shorthand /insights 7 (no flag) must not be mangled.""" + assert _normalize_insights_args("7") == "7" + + def test_no_flags_unchanged(self): + """Input with no flags passes through as-is.""" + assert _normalize_insights_args("") == "" + assert _normalize_insights_args("30") == "30"