diff --git a/gateway/platforms/slack.py b/gateway/platforms/slack.py index d35b703f..f60b6bee 100644 --- a/gateway/platforms/slack.py +++ b/gateway/platforms/slack.py @@ -2695,9 +2695,14 @@ class SlackAdapter(BasePlatformAdapter): # gateway command dispatcher by prepending the slash. text = f"/{slash_name} {text}".strip() + # Slack slash commands can originate from DMs or shared channels. + # Preserve DM semantics only for DM channel IDs; shared channels must + # keep group semantics so different users do not collide into one + # session key. + is_dm = str(channel_id).startswith("D") source = self.build_source( chat_id=channel_id, - chat_type="dm", # Slash commands are always in DM-like context + chat_type="dm" if is_dm else "group", user_id=user_id, ) diff --git a/tests/gateway/test_slack.py b/tests/gateway/test_slack.py index 35c49d1c..c45cc53a 100644 --- a/tests/gateway/test_slack.py +++ b/tests/gateway/test_slack.py @@ -92,6 +92,46 @@ def _redirect_cache(tmp_path, monkeypatch): ) +# --------------------------------------------------------------------------- +# TestSlashCommandSessionIsolation +# --------------------------------------------------------------------------- + +class TestSlashCommandSessionIsolation: + @pytest.mark.asyncio + async def test_channel_slash_command_uses_group_session_semantics(self, adapter): + command = { + "text": "hello", + "user_id": "U123", + "channel_id": "C123", + "team_id": "T123", + } + + await adapter._handle_slash_command(command) + + adapter.handle_message.assert_awaited_once() + event = adapter.handle_message.await_args.args[0] + assert event.source.chat_type == "group" + assert event.source.chat_id == "C123" + assert event.source.user_id == "U123" + + @pytest.mark.asyncio + async def test_dm_slash_command_keeps_dm_session_semantics(self, adapter): + command = { + "text": "hello", + "user_id": "U123", + "channel_id": "D123", + "team_id": "T123", + } + + await adapter._handle_slash_command(command) + + adapter.handle_message.assert_awaited_once() + event = adapter.handle_message.await_args.args[0] + assert event.source.chat_type == "dm" + assert event.source.chat_id == "D123" + assert event.source.user_id == "U123" + + # --------------------------------------------------------------------------- # TestAppMentionHandler # ---------------------------------------------------------------------------