Files
Breehavior-Monitor/config.yaml
AJ Isaacs 90b70cad69 feat: channel-level conversation analysis with compact formatting
Switch from per-user message batching to per-channel conversation
analysis. The LLM now sees the full interleaved conversation with
relative timestamps, reply chains, and consecutive message collapsing
instead of isolated flat text per user.

Key changes:
- Fix gpt-5-nano temperature incompatibility (conditional temp param)
- Add mention-triggered scan: users @mention bot to analyze recent chat
- Refactor debounce buffer from (channel_id, user_id) to channel_id
- Replace per-message analyze_message() with analyze_conversation()
  returning per-user findings from a single LLM call
- Add CONVERSATION_TOOL schema with coherence, topic, and game fields
- Compact message format: relative timestamps, reply arrows (→),
  consecutive same-user message collapsing
- Separate mention scan tasks from debounce tasks
- Remove _store_context/_get_context (conversation block IS the context)
- Escalation timeout config: [30, 60, 120, 240] minutes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 23:13:07 -05:00

155 lines
5.7 KiB
YAML

bot:
prefix: "!"
status: "Monitoring vibes..."
monitoring:
dry_run: false # Log analysis results to channel but don't warn/mute
enabled: true
channels: [] # Empty = monitor all channels. Add channel IDs to limit.
ignored_users: [] # User IDs to never monitor (bot owner, etc.)
immune_roles: [] # Role IDs that are immune to monitoring
sentiment:
warning_threshold: 0.6
mute_threshold: 0.65
spike_warning_threshold: 0.5 # Single message score that triggers instant warning
spike_mute_threshold: 0.7 # Single message score that triggers instant mute
context_messages: 8 # Number of previous messages to include as context
rolling_window_size: 10 # Number of messages to track per user
rolling_window_minutes: 15 # Time window for tracking
batch_window_seconds: 10 # Wait this long for more messages before analyzing (debounce)
escalation_threshold: 0.25 # Triage toxicity score that triggers re-analysis with heavy model
game_channels:
gta-online: "GTA Online"
battlefield: "Battlefield"
warzone: "Call of Duty: Warzone"
cod-zombies: "Call of Duty: Zombies"
topic_drift:
enabled: true
ignored_channels: ["general"] # Channel names or IDs to skip topic drift monitoring
remind_cooldown_minutes: 10 # Don't remind same user more than once per this window
escalation_count: 3 # After this many reminds, DM the server owner
reset_minutes: 60 # Reset off-topic count after this much on-topic behavior
mention_scan:
enabled: true
scan_messages: 30 # Messages to scan per mention trigger
cooldown_seconds: 60 # Per-channel cooldown between scans
timeouts:
escalation_minutes: [30, 60, 120, 240] # Escalating timeout durations
offense_reset_minutes: 120 # Reset offense counter after this much good behavior
warning_cooldown_minutes: 5 # Don't warn same user more than once per this window
messages:
warning: "Easy there, {username}. The Breehavior Monitor is watching. \U0001F440"
mute_title: "\U0001F6A8 BREEHAVIOR ALERT \U0001F6A8"
mute_description: "{username} has been placed in timeout for {duration}.\n\nReason: Sustained elevated drama levels detected.\nDrama Score: {score}/1.0\nCategories: {categories}\n\nCool down and come back when you've resolved your skill issues."
topic_remind: "Hey {username}, this is a gaming server \U0001F3AE — maybe take the personal stuff to DMs?"
topic_nudge: "{username}, we've chatted about this before — let's keep it to gaming talk in here. Personal drama belongs in DMs."
topic_owner_dm: "Heads up: {username} keeps going off-topic with personal drama in #{channel}. They've been reminded {count} times. Might need a word."
channel_redirect: "Hey {username}, that sounds like {game} talk — head over to {channel} for that!"
modes:
default_mode: roast
proactive_cooldown_messages: 8 # Minimum messages between proactive replies
default:
label: "Default"
description: "Hall-monitor moderation mode"
prompt_file: "chat_personality.txt"
proactive_replies: false
reply_chance: 0.0
moderation: full
chatty:
label: "Chatty"
description: "Friendly chat participant"
prompt_file: "chat_chatty.txt"
proactive_replies: true
reply_chance: 0.10
moderation: relaxed
relaxed_thresholds:
warning_threshold: 0.80
mute_threshold: 0.85
spike_warning_threshold: 0.70
spike_mute_threshold: 0.85
roast:
label: "Roast"
description: "Savage roast mode"
prompt_file: "chat_roast.txt"
proactive_replies: true
reply_chance: 0.20
moderation: relaxed
relaxed_thresholds:
warning_threshold: 0.85
mute_threshold: 0.90
spike_warning_threshold: 0.75
spike_mute_threshold: 0.90
hype:
label: "Hype"
description: "Your biggest fan"
prompt_file: "chat_hype.txt"
proactive_replies: true
reply_chance: 0.15
moderation: relaxed
relaxed_thresholds:
warning_threshold: 0.80
mute_threshold: 0.85
spike_warning_threshold: 0.70
spike_mute_threshold: 0.85
drunk:
label: "Drunk"
description: "Had a few too many"
prompt_file: "chat_drunk.txt"
proactive_replies: true
reply_chance: 0.20
moderation: relaxed
relaxed_thresholds:
warning_threshold: 0.85
mute_threshold: 0.90
spike_warning_threshold: 0.75
spike_mute_threshold: 0.90
english_teacher:
label: "English Teacher"
description: "Insufferable grammar nerd mode"
prompt_file: "chat_english_teacher.txt"
proactive_replies: true
reply_chance: 0.20
moderation: relaxed
relaxed_thresholds:
warning_threshold: 0.85
mute_threshold: 0.90
spike_warning_threshold: 0.75
spike_mute_threshold: 0.90
polls:
enabled: true
duration_hours: 4
cooldown_minutes: 60 # Per-channel cooldown between auto-polls
wordle:
enabled: true
bot_name: "Wordle" # Discord bot name to watch for
reply_chance: 0.75 # Chance to comment on result summaries (0.0-1.0)
playing_reply_chance: 0.0 # Chance to comment on "was playing" messages (0 = never)
coherence:
enabled: true
drop_threshold: 0.3 # How far below baseline triggers alert
absolute_floor: 0.5 # Don't alert if score is above this regardless
cooldown_minutes: 30 # Don't alert same user more than once per window
messages:
intoxicated: "Someone get {username} some water... or maybe cut them off."
tired: "{username} might need some sleep, that message was rough."
angry_typing: "{username} is typing so hard their keyboard is scared."
mobile_keyboard: "{username}'s thumbs are having a rough day."
language_barrier: "Having trouble there, {username}? Take your time."
default: "You okay there, {username}? That message was... something."