AI generated first iteration
This commit is contained in:
105
app/agent/policies.py
Normal file
105
app/agent/policies.py
Normal file
@@ -0,0 +1,105 @@
|
||||
"""Agent behavior policies and rules."""
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ChatActivityPolicy:
|
||||
"""Policy for detecting chat activity and inactivity periods."""
|
||||
|
||||
def __init__(self, inactivity_threshold_minutes: int = 15):
|
||||
"""
|
||||
Initialize policy.
|
||||
|
||||
Args:
|
||||
inactivity_threshold_minutes: Minutes of no chat before Hearthkeeper activates
|
||||
"""
|
||||
self.inactivity_threshold = timedelta(minutes=inactivity_threshold_minutes)
|
||||
self.last_message_time: dict[str, datetime] = {}
|
||||
|
||||
def record_activity(self, session_id: str) -> None:
|
||||
"""Record that chat activity occurred."""
|
||||
self.last_message_time[session_id] = datetime.utcnow()
|
||||
|
||||
def minutes_since_activity(self, session_id: str) -> int:
|
||||
"""Get minutes since last chat message."""
|
||||
if session_id not in self.last_message_time:
|
||||
return 0
|
||||
elapsed = datetime.utcnow() - self.last_message_time[session_id]
|
||||
return int(elapsed.total_seconds() / 60)
|
||||
|
||||
def should_hearthkeeper_prompt(self, session_id: str) -> bool:
|
||||
"""Determine if Hearthkeeper should send a prompt."""
|
||||
minutes = self.minutes_since_activity(session_id)
|
||||
should = minutes >= self.inactivity_threshold.total_seconds() / 60
|
||||
if should:
|
||||
logger.info(f"Chat inactive for {minutes} minutes. Hearthkeeper may prompt.")
|
||||
return should
|
||||
|
||||
|
||||
class ResponseSuppression:
|
||||
"""Policy for when the agent should NOT respond."""
|
||||
|
||||
# Suppress responses when chat is very active (humans are talking)
|
||||
ACTIVE_CHAT_THRESHOLD = 5 # 5+ messages per minute = suppress
|
||||
|
||||
@staticmethod
|
||||
def should_suppress_response(recent_message_count: int, time_window_minutes: int = 1) -> bool:
|
||||
"""
|
||||
Determine if agent should stay silent due to active chat.
|
||||
|
||||
Args:
|
||||
recent_message_count: Number of messages in the time window
|
||||
time_window_minutes: Time window in minutes
|
||||
|
||||
Returns:
|
||||
True if agent should suppress response
|
||||
"""
|
||||
messages_per_minute = recent_message_count / time_window_minutes
|
||||
suppress = messages_per_minute >= ResponseSuppression.ACTIVE_CHAT_THRESHOLD
|
||||
|
||||
if suppress:
|
||||
logger.debug(f"Response suppressed due to active chat ({messages_per_minute:.1f} msg/min)")
|
||||
|
||||
return suppress
|
||||
|
||||
|
||||
class SuspiciousContentPolicy:
|
||||
"""Policy for detecting suspicious content."""
|
||||
|
||||
# Patterns that raise Warden alerts
|
||||
SUSPICIOUS_KEYWORDS = [
|
||||
"join our discord",
|
||||
"discord.gg",
|
||||
"grow your channel",
|
||||
"easy money",
|
||||
"limited offer",
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def is_suspicious(message: str) -> bool:
|
||||
"""
|
||||
Check if a message matches suspicious patterns.
|
||||
|
||||
Args:
|
||||
message: Message content
|
||||
|
||||
Returns:
|
||||
True if message is suspicious
|
||||
"""
|
||||
message_lower = message.lower()
|
||||
|
||||
for keyword in SuspiciousContentPolicy.SUSPICIOUS_KEYWORDS:
|
||||
if keyword in message_lower:
|
||||
logger.warning(f"Suspicious content detected: {keyword}")
|
||||
return True
|
||||
|
||||
# Check for multiple links
|
||||
link_count = message.count("http") + message.count("www")
|
||||
if link_count > 1:
|
||||
logger.warning("Suspicious content detected: multiple links")
|
||||
return True
|
||||
|
||||
return False
|
||||
Reference in New Issue
Block a user