"""One-shot patch: append natural-chat / media-request tests to test_companion_chat.py.""" from pathlib import Path path = Path(__file__).resolve().parent / "tests" / "test_companion_chat.py" text = path.read_text(encoding="utf-8") # The provider's detector is imported directly: the tests pin the same function # the service reads for its generation flags. old_import = """from app.services.providers.chat_provider import ( LocalCompanionChatProvider, OpenAICompanionChatProvider, )""" new_import = """from app.services.providers.chat_provider import ( LocalCompanionChatProvider, OpenAICompanionChatProvider, detect_media_request, )""" assert old_import in text, "import block not found" text = text.replace(old_import, new_import, 1) ADDITIONS = ''' # --------------------------------------------------------------------------- # Media requests: pic / photo / image / selfie and video / clip # --------------------------------------------------------------------------- GENERIC_DEFLECTIONS = ( "interesting question", "i'm glad you told me", "i'm glad you shared that", "i hear you, darling", ) def test_media_requests_are_detected_for_pics_photos_selfies_and_clips(): """Every everyday way of asking for a picture or a clip is recognised.""" cases = [ ("send me a pic", True, False), ("give me a photo of you", True, False), ("can you send a selfie?", True, False), ("image please", True, False), ("a clip please", False, True), ("send me a video", False, True), ("send me a romantic picture", True, False), ("make me a short clip of you waving", False, True), ] for message, expected_image, expected_video in cases: wants_image, wants_video, _ = detect_media_request(message) assert wants_image is expected_image, message assert wants_video is expected_video, message def test_ordinary_talk_about_photos_is_not_a_generation_request(): """Mentioning a picture is not asking for one - no accidental jobs.""" assert detect_media_request("I saw a lovely photo in a gallery today") == (False, False, "") def test_image_request_acknowledgement_changes_every_time_and_keeps_the_style(): """While the picture renders the companion says something new, not "OK".""" provider = LocalCompanionChatProvider() replies = [ asyncio.run( provider.generate_response(make_character(), "send me a romantic picture", [], []) )[0] for _ in range(3) ] assert len(set(replies)) == len(replies), replies for reply in replies: assert "romantic" in reply, reply assert "picture" in reply or "photo" in reply, reply def test_video_request_acknowledgement_talks_about_the_video(): reply, *_ = asyncio.run( LocalCompanionChatProvider().generate_response( make_character(), "send me a romantic clip", [], [] ) ) assert "video" in reply or "clip" in reply, reply assert "picture" not in reply, reply def test_casual_chat_replies_answer_the_users_words_without_stock_lines(): """No "Interesting question…" / "I'm glad you told me…" style deflections.""" reply, *_ = asyncio.run( LocalCompanionChatProvider().generate_response( make_character(), "The sky looks lovely tonight.", [], [] ) ) low = reply.lower() for phrase in GENERIC_DEFLECTIONS: assert phrase not in low, reply assert "sky" in low or "tonight" in low, reply assert "darling" in low def test_the_saved_personality_shapes_the_reply(): """Two companions answer one message differently, each in her saved voice.""" provider = LocalCompanionChatProvider() message = "I fixed the trickiest bug of my week." histories = [ [], [ChatMessage(role="assistant", content="Mmhm.")], [ ChatMessage(role="assistant", content="Mmhm."), ChatMessage(role="assistant", content="Yeah."), ], [ ChatMessage(role="assistant", content="Mmhm."), ChatMessage(role="assistant", content="Yeah."), ChatMessage(role="assistant", content="Mm."), ], ] playful = [ asyncio.run( provider.generate_response( make_character(name="Mira", personality="Playful and teasing at all times"), message, history, [], ) )[0] for history in histories ] witty = [ asyncio.run( provider.generate_response(make_character(), message, history, []) )[0] for history in histories ] assert any("teasing you" in reply for reply in playful), playful assert any("on my toes" in reply for reply in witty), witty assert set(playful) != set(witty) ''' if not text.endswith("\n"): text += "\n" text += ADDITIONS.lstrip("\n") path.write_text(text, encoding="utf-8") print("patched", path)