From 1deeaf71abcf84d9f5d4d8255abfd5654a0ed2e1 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Tue, 7 Jul 2026 04:30:11 -0700 Subject: [PATCH] fix(discord): truncate thread titles by UTF-16 units + AUTHOR_MAP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discord thread names share the same UTF-16 component budget as select labels and buttons — route the sanitizers in gateway/run.py and the adapter's rename_thread through utf16_len/_prefix_within_utf16_limit instead of code-point slices. Adds rungmc357 to AUTHOR_MAP. --- gateway/run.py | 13 ++++++++++--- plugins/platforms/discord/adapter.py | 7 +++++-- scripts/release.py | 1 + 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/gateway/run.py b/gateway/run.py index 3102f883430..af7f5c7b46c 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -1761,8 +1761,10 @@ from gateway.platforms.base import ( EphemeralReply, MessageEvent, MessageType, + _prefix_within_utf16_limit, _reply_anchor_for_event, merge_pending_message_event, + utf16_len, ) from gateway.restart import ( DEFAULT_GATEWAY_RESTART_DRAIN_TIMEOUT, @@ -13328,12 +13330,17 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew ) def _sanitize_discord_thread_title(self, title: str) -> str: - """Return a Discord-safe semantic thread title from a session title.""" + """Return a Discord-safe semantic thread title from a session title. + + Discord thread names are capped at 100 characters measured in UTF-16 + code units (emoji count double), so truncate with the UTF-16 helpers + rather than Python code-point slices. + """ cleaned = re.sub(r"\s+", " ", str(title or "")).strip() if not cleaned: return "Hermes Chat" - if len(cleaned) > 80: - cleaned = cleaned[:77].rstrip() + "..." + if utf16_len(cleaned) > 80: + cleaned = _prefix_within_utf16_limit(cleaned, 77).rstrip() + "..." return cleaned async def _rename_discord_auto_thread_for_session_title( diff --git a/plugins/platforms/discord/adapter.py b/plugins/platforms/discord/adapter.py index 755ad69a8fe..641215bd705 100644 --- a/plugins/platforms/discord/adapter.py +++ b/plugins/platforms/discord/adapter.py @@ -5271,8 +5271,11 @@ class DiscordAdapter(BasePlatformAdapter): cleaned = re.sub(r"\s+", " ", str(name or "")).strip() if not cleaned: return False - if len(cleaned) > 80: - cleaned = cleaned[:77].rstrip() + "..." + # Discord thread names are budgeted in UTF-16 code units (emoji count + # double) — truncate with the UTF-16 helpers, not code-point slices. + from gateway.platforms.base import utf16_len, _prefix_within_utf16_limit + if utf16_len(cleaned) > 80: + cleaned = _prefix_within_utf16_limit(cleaned, 77).rstrip() + "..." try: thread = self._client.get_channel(thread_id_int) diff --git a/scripts/release.py b/scripts/release.py index a1a699e5e39..9127dc38410 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -290,6 +290,7 @@ AUTHOR_MAP = { "290859878+synapsesx@users.noreply.github.com": "synapsesx", "157689911+itsflownium@users.noreply.github.com": "itsflownium", "dirtyren@users.noreply.github.com": "dirtyren", + "210088133+rungmc357@users.noreply.github.com": "rungmc357", "florian.rutishauser@outlook.com": "flo1t", "fanyang@microsoft.com": "fanyangCS", "bigstar0920@gmail.com": "bigstar0920",