fix(gateway): preserve case-sensitive chat IDs in DeliveryTarget.parse

Fixes NousResearch/hermes-agent#11768

Root cause: target.strip().lower() was lowercasing the entire target string,
corrupting case-sensitive chat IDs like Slack C123ABC and Matrix !RoomABC.

Fix: Only lowercase the platform prefix for case-insensitive matching;
preserve the original case for chat_id and thread_id values.
This commit is contained in:
nightq
2026-04-18 09:55:21 +08:00
committed by kshitij
parent 2b3923ff13
commit 5cdc39e29a
2 changed files with 67 additions and 7 deletions

View File

@@ -65,4 +65,62 @@ class TestTargetToStringRoundtrip:
assert reparsed.chat_id == "999"
class TestCaseSensitiveChatIdParsing:
"""Test that chat IDs preserve their original case (issue #11768)."""
def test_slack_uppercase_chat_id_preserved(self):
"""Slack channel IDs like C123ABC should preserve case."""
target = DeliveryTarget.parse("slack:C123ABC")
assert target.platform == Platform.SLACK
assert target.chat_id == "C123ABC" # Should NOT be lowercased to c123abc
assert target.is_explicit is True
def test_slack_chat_id_with_thread_preserved(self):
"""Slack channel:thread IDs should preserve case."""
target = DeliveryTarget.parse("slack:C123ABC:thread123")
assert target.platform == Platform.SLACK
assert target.chat_id == "C123ABC"
assert target.thread_id == "thread123"
def test_matrix_room_id_preserved(self):
"""Matrix room IDs like !RoomABC:example.org should preserve case.
Note: Matrix room IDs contain colons (e.g., !RoomABC:example.org).
Due to the platform:chat_id:thread_id format, these are parsed as
chat_id=!RoomABC and thread_id=example.org. This is a known limitation
of the current format. The fix preserves case but doesn't change the
parsing structure.
"""
target = DeliveryTarget.parse("matrix:!RoomABC:example.org")
assert target.platform == Platform.MATRIX
# The room ID is split at the first colon after the platform prefix
# This is a format limitation - the case is preserved but the structure is split
assert target.chat_id == "!RoomABC"
assert target.thread_id == "example.org"
def test_mixed_case_chat_id_roundtrip(self):
"""Mixed-case chat IDs should survive parse-to_string roundtrip."""
original = "telegram:ChatId123ABC"
target = DeliveryTarget.parse(original)
s = target.to_string()
reparsed = DeliveryTarget.parse(s)
assert reparsed.chat_id == "ChatId123ABC"
class TestPlatformNameCaseInsensitivity:
"""Test that platform names are case-insensitive."""
def test_uppercase_platform_name(self):
"""Platform names should be case-insensitive."""
target = DeliveryTarget.parse("TELEGRAM:12345")
assert target.platform == Platform.TELEGRAM
assert target.chat_id == "12345"
def test_mixed_case_platform_name(self):
"""Mixed-case platform names should work."""
target = DeliveryTarget.parse("TeleGram:12345")
assert target.platform == Platform.TELEGRAM
assert target.chat_id == "12345"