feat: unified group modes (open/listen/mention-only) (#267)

Consolidates listeningGroups and groups.requireMention into a single
groups config with explicit mode per group. Backward compatible --
legacy formats auto-normalize with deprecation warnings.

- Add shared group-mode.ts with isGroupAllowed/resolveGroupMode helpers
- Update all 5 channel adapters to use mode-based gating
- Default to mention-only for configured entries (safe), open when no config
- Listening mode now set at adapter level, bot.ts has legacy fallback
- Fix YAML large-ID parsing for groups map keys (Discord snowflakes)
- Add migration in normalizeAgents for listeningGroups + requireMention
- Add unit tests for group-mode helpers + update all gating tests
- Update docs, README, and example config

Closes #266

Written by Cameron and Letta Code

"Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away." -- Antoine de Saint-Exupery
This commit is contained in:
Cameron
2026-02-10 16:01:21 -08:00
committed by GitHub
parent 745291841d
commit c410decd18
23 changed files with 677 additions and 274 deletions

View File

@@ -38,27 +38,25 @@ channels:
dmPolicy: pairing # 'pairing', 'allowlist', or 'open'
# groupPollIntervalMin: 5 # Batch interval for group messages (default: 10)
# instantGroups: ["-100123456"] # Groups that bypass batching
# listeningGroups: ["-100123456"] # Groups where bot observes but only replies when @mentioned
# Group access control (which groups can interact, mention requirement):
# Group access + response mode:
# groups:
# "*": { requireMention: true } # Default: only respond when @mentioned
# "-1001234567890": { requireMention: false } # This group gets all messages
# "*": { mode: listen } # Observe all groups; only reply when @mentioned
# "-1001234567890": { mode: open } # This group gets all messages
# "-1009876543210": { mode: mention-only } # Drop unless @mentioned
# mentionPatterns: ["hey bot"] # Additional regex patterns for mention detection
# slack:
# enabled: true
# appToken: xapp-...
# botToken: xoxb-...
# listeningGroups: ["C0123456789"] # Channels where bot observes only
# # groups:
# # "*": { requireMention: true } # Default: only respond when @mentioned
# # "C0123456789": { requireMention: false }
# groups:
# "*": { mode: listen }
# "C0123456789": { mode: open }
# discord:
# enabled: true
# token: YOUR-DISCORD-BOT-TOKEN
# listeningGroups: ["1234567890123456789"] # Server/channel IDs where bot observes only
# # groups:
# # "*": { requireMention: true } # Default: only respond when @mentioned
# # "1234567890123456789": { requireMention: false } # Server or channel ID
# groups:
# "*": { mode: listen }
# "1234567890123456789": { mode: open } # Server or channel ID
# whatsapp:
# enabled: true
# selfChat: false