""" Tests for Behavior Policy v2.1 Aligned with Global System Prompt v2.1 — FINAL Tests cover: - Broadcast detection - Imperative/explicit request detection - Mention detection - SOWA: DM always responds - SOWA: Mentioned + explicit_request -> responds - SOWA: Broadcast without mention -> NO_OUTPUT - SOWA: Media/link without request -> NO_OUTPUT - SOWA: Media + mention -> responds - SOWA: Bare mention in public -> NO_OUTPUT (v2.1 anti-spam) - SOWA: Bare mention in DM -> responds - SOWA: Question without mention in topic -> NO_OUTPUT - URL detection - Reply to agent """ import pytest import sys import os # Add gateway-bot to path sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'gateway-bot')) from behavior_policy import ( analyze_message, should_respond, detect_agent_mention, detect_broadcast_intent, detect_question, detect_imperative, detect_url, detect_explicit_request, detect_short_note, detect_media_question, ) # ===== Broadcast Detection ===== class TestBroadcastDetection: def test_time_pattern(self): assert detect_broadcast_intent("20:00 10.02 Deployed") def test_emoji_start(self): assert detect_broadcast_intent("\u26a1 Оновлення системи") def test_announcement_word(self): assert detect_broadcast_intent("увага всім! нова версія") def test_url_only(self): assert detect_broadcast_intent("https://example.com") def test_normal_message_not_broadcast(self): assert not detect_broadcast_intent("Допоможи з налаштуванням") # ===== Imperative Detection ===== class TestImperativeDetection: def test_ua_imperative(self): assert detect_imperative("Допоможи з налаштуванням") def test_ua_analyze(self): assert detect_imperative("Проаналізуй логи") def test_en_fix(self): assert detect_imperative("Fix this bug") def test_en_explain(self): assert detect_imperative("Explain how it works") def test_no_imperative(self): assert not detect_imperative("Просто повідомлення") # ===== Explicit Request Detection (Gateway level) ===== class TestExplicitRequestDetection: def test_imperative_triggers(self): assert detect_explicit_request("Допоможи з налаштуванням") def test_question_with_mention(self): assert detect_explicit_request("Що це?", mentioned_agents=['helion']) def test_question_in_dm(self): assert detect_explicit_request("Що це?", is_dm=True) def test_question_without_context(self): assert not detect_explicit_request("Що це?") def test_no_question_no_imperative(self): assert not detect_explicit_request("Просто текст без питання") # ===== Question Detection ===== class TestQuestionDetection: def test_with_question_mark(self): assert detect_question("Що це таке?") def test_without_question_mark(self): assert not detect_question("Що нового в проекті") # ===== Mention Detection ===== class TestMentionDetection: def test_helion_at_mention(self): assert detect_agent_mention("@Helion що на постері?", "helion") def test_helion_name(self): assert detect_agent_mention("Helion, допоможи", "helion") def test_ua_name(self): assert detect_agent_mention("хеліон, що скажеш?", "helion") def test_no_mention(self): assert not detect_agent_mention("Хто знає відповідь?", "helion") # ===== URL Detection ===== class TestURLDetection: def test_https(self): assert detect_url("Check https://example.com") def test_www(self): assert detect_url("Visit www.github.com") def test_telegram(self): assert detect_url("Join t.me/channel") def test_telegram_me(self): assert detect_url("Link: telegram.me/bot") def test_no_link(self): assert not detect_url("No link here") # ===== SOWA: DM Always Responds ===== class TestSOWADMAlwaysResponds: def test_dm_responds(self): decision = analyze_message( text="Привіт", agent_id="helion", chat_id="123", user_id="456", is_private_chat=True, ) assert decision.should_respond assert decision.reason == "private_chat" # ===== SOWA: Mentioned + Request ===== class TestSOWAMentionedWithRequest: def test_mentioned_with_request(self): decision = analyze_message( text="@Helion що змінилось у v2.0?", agent_id="helion", chat_id="-100123", user_id="456", is_private_chat=False, payload_explicit_request=True, ) assert decision.should_respond assert decision.reason == "mentioned_with_request" # ===== SOWA: Broadcast Without Mention ===== class TestSOWABroadcastNoMention: def test_broadcast_no_mention(self): resp, reason = should_respond( text="\u26a1 Оновлення: релізимо v2.0", agent_id="helion", chat_id="-100123", user_id="456", is_private_chat=False, ) assert not resp assert reason == "broadcast_not_directed" # ===== SOWA: Media Without Request ===== class TestSOWAMediaWithoutRequest: def test_media_no_request(self): resp, reason = should_respond( text="", agent_id="helion", chat_id="-100123", user_id="456", has_media=True, is_private_chat=False, payload_explicit_request=False, ) assert not resp assert reason == "media_or_link_without_request" # ===== SOWA: Media + Mention ===== class TestSOWAMediaWithMention: def test_media_with_mention(self): decision = analyze_message( text="@Helion що на фото?", agent_id="helion", chat_id="-100123", user_id="456", has_media=True, media_caption="@Helion що на фото?", is_private_chat=False, payload_explicit_request=True, ) assert decision.should_respond assert decision.reason == "mentioned_with_request" # ===== v2.1: Bare Mention in Public = NO_OUTPUT ===== class TestSOWABareMentionPublicNoResponse: def test_bare_mention_public(self): resp, reason = should_respond( text="@Helion", agent_id="helion", chat_id="-100123", user_id="456", is_private_chat=False, payload_explicit_request=False, ) assert not resp assert reason == "bare_mention_public_topic" # ===== v2.1: Bare Mention in DM = Responds ===== class TestSOWABareMentionDMResponds: def test_bare_mention_dm(self): resp, reason = should_respond( text="@Helion", agent_id="helion", chat_id="123", user_id="456", is_private_chat=True, payload_explicit_request=False, ) assert resp assert reason == "private_chat" # ===== SOWA: Question Without Mention in Topic ===== class TestSOWAQuestionWithoutMentionInTopic: def test_question_no_mention_topic(self): resp, reason = should_respond( text="Хто знає чому падає сервер?", agent_id="helion", chat_id="-100123", user_id="456", is_private_chat=False, payload_explicit_request=False, ) assert not resp assert reason == "not_directed_to_agent" # ===== SOWA: Reply to Agent ===== class TestSOWAReplyToAgent: def test_reply_to_agent(self): resp, reason = should_respond( text="А що з цим робити?", agent_id="helion", chat_id="-100123", user_id="456", is_private_chat=False, is_reply_to_agent=True, ) assert resp assert reason == "reply_to_agent" # ===== Short Notes ===== class TestShortNotes: def test_checkmark(self): assert detect_short_note("\u2705") def test_ok(self): assert detect_short_note("ok") def test_plus(self): assert detect_short_note("+") def test_normal_message(self): assert not detect_short_note("Це нормальне повідомлення") if __name__ == "__main__": pytest.main([__file__, "-v"])