hermes-agent/tests/agent/test_reactions.py
Brooklyn Nicholson 422d9da9bd feat(agent): core affection reaction detector + reaction_callback
Add a token-free, curated affection matcher (agent/reactions.py) — the single
source of truth for detecting user "vibes" (ily / <3 / good bot / heart emoji).
No model call, no tokens. Generalized to return a reaction *kind* so future
reactions can ride the same signal.

Wire an opt-in AIAgent.reaction_callback that fires from build_turn_context on
the incoming user message. It never touches the conversation (cache-safe) and
never fatal — a purely cosmetic side-beat each host can consume.
2026-07-10 05:41:59 -05:00

56 lines
1.3 KiB
Python

"""Behavior tests for the token-free reaction detector."""
import pytest
from agent.reactions import VIBE, detect_reaction
@pytest.mark.parametrize(
"text",
[
"good bot",
"Good Bot!",
"ily",
"ilysm",
"i love you",
"love you",
"love u",
"luv ya",
"thanks",
"thank you",
"thx",
"ty",
"tysm",
"you're the best <3",
"here you go <33",
"❤️",
"🥰 amazing",
"sending 💖",
"great job, thank you so much!",
],
)
def test_affection_fires_vibe(text):
assert detect_reaction(text) == VIBE
@pytest.mark.parametrize(
"text",
[
"",
None,
"run the tests",
"this is great", # positive sentiment, NOT affection — must not fire
"awesome work on the refactor",
"it's broken </3", # broken heart is not affection
"the ferry departs at 3", # 'ty' must be word-bounded, not match 'ferTY'-like
"commit the changes",
],
)
def test_neutral_or_negative_does_not_fire(text):
assert detect_reaction(text) is None
def test_case_insensitive_invariant():
# Casing must never change the classification.
for text in ("ILY", "iLy", "ily"):
assert detect_reaction(text) == detect_reaction("ily")