Files
microdao-daarion/services/agent-filter/rules.py

120 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from models import MessageCreatedEvent, FilterContext, FilterDecision
from datetime import datetime, time
import yaml
import os
class FilterRules:
def __init__(self, config_path: str = "config.yaml"):
if os.path.exists(config_path):
with open(config_path, 'r') as f:
self.config = yaml.safe_load(f)
else:
# Default config
self.config = {
'rules': {
'quiet_hours': {
'start': '23:00',
'end': '07:00'
},
'default_agents': {
'microdao:daarion': 'agent:sofia',
'microdao:7': 'agent:sofia'
}
}
}
self.quiet_hours_start = datetime.strptime(
self.config['rules']['quiet_hours']['start'],
"%H:%M"
).time()
self.quiet_hours_end = datetime.strptime(
self.config['rules']['quiet_hours']['end'],
"%H:%M"
).time()
self.default_agents = self.config['rules'].get('default_agents', {})
def is_quiet_hours(self, dt: datetime) -> bool:
"""Check if current time is in quiet hours"""
current_time = dt.time()
if self.quiet_hours_start > self.quiet_hours_end:
# Overnight range (e.g., 23:00 - 07:00)
return current_time >= self.quiet_hours_start or current_time <= self.quiet_hours_end
else:
return self.quiet_hours_start <= current_time <= self.quiet_hours_end
def decide(self, event: MessageCreatedEvent, ctx: FilterContext) -> FilterDecision:
"""
Apply filtering rules and decide if/which agent should respond
Rules:
1. Block agent→agent loops
2. Check if agent is disabled
3. Find target agent (from allowed_agents or default)
4. Apply quiet hours modifier
5. Allow or deny
"""
base_decision = FilterDecision(
channel_id=event.channel_id,
message_id=event.message_id,
matrix_event_id=event.matrix_event_id,
microdao_id=event.microdao_id,
decision="deny"
)
# Rule 1: Block agent→agent loops
if event.sender_type == "agent":
print(f"[FILTER] Denying: sender is agent (loop prevention)")
return base_decision
# Rule 2: Check if any agents are disabled
if ctx.channel.disabled_agents:
print(f"[FILTER] Warning: Some agents are disabled: {ctx.channel.disabled_agents}")
# Rule 3: Find target agent
target_agent_id = None
if ctx.channel.allowed_agents:
target_agent_id = ctx.channel.allowed_agents[0]
print(f"[FILTER] Target agent from allowed_agents: {target_agent_id}")
elif event.microdao_id in self.default_agents:
target_agent_id = self.default_agents[event.microdao_id]
print(f"[FILTER] Target agent from default: {target_agent_id}")
if not target_agent_id:
print(f"[FILTER] Denying: no target agent found for {event.microdao_id}")
return base_decision
# Check if target agent is disabled
if target_agent_id in ctx.channel.disabled_agents:
print(f"[FILTER] Denying: target agent {target_agent_id} is disabled")
return base_decision
# Rule 4: Check quiet hours
if ctx.local_time and self.is_quiet_hours(ctx.local_time):
print(f"[FILTER] Quiet hours active, modifying prompt")
return FilterDecision(
channel_id=event.channel_id,
message_id=event.message_id,
matrix_event_id=event.matrix_event_id,
microdao_id=event.microdao_id,
decision="modify",
target_agent_id=target_agent_id,
rewrite_prompt="Відповідай стисло і тільки якщо запит важливий. Не ініціюй розмову сам."
)
# Rule 5: Allow
print(f"[FILTER] Allowing: {target_agent_id} to respond")
return FilterDecision(
channel_id=event.channel_id,
message_id=event.message_id,
matrix_event_id=event.matrix_event_id,
microdao_id=event.microdao_id,
decision="allow",
target_agent_id=target_agent_id
)