Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions internal/channels/discord/discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ type Channel struct {
audioMgr *audio.Manager // unified STT via audio.Manager (nil = no STT)
// pairingService, pairingDebounce, approvedGroups, groupHistory, historyLimit, requireMention
// are inherited from channels.BaseChannel.

// mentionedThreads tracks thread/channel IDs where the bot was @mentioned.
// Once mentioned in a thread, respond to ALL subsequent messages without requiring another mention.
mentionedThreads map[string]bool
mentionedThreadsMu sync.Mutex
}

// New creates a new Discord channel from config.
Expand Down Expand Up @@ -66,12 +71,13 @@ func New(cfg config.DiscordConfig, msgBus *bus.MessageBus, pairingSvc store.Pair
}

ch := &Channel{
BaseChannel: base,
session: session,
config: cfg,
agentStore: agentStore,
configPermStore: configPermStore,
audioMgr: audioMgr,
BaseChannel: base,
session: session,
config: cfg,
agentStore: agentStore,
configPermStore: configPermStore,
audioMgr: audioMgr,
mentionedThreads: make(map[string]bool),
}
ch.SetRequireMention(requireMention)
ch.SetPairingService(pairingSvc)
Expand Down
28 changes: 27 additions & 1 deletion internal/channels/discord/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,33 @@ func (c *Channel) handleMessage(_ *discordgo.Session, m *discordgo.MessageCreate
// When not mentioned, record message to pending history for later context.
// `mentioned` was pre-computed above for policy gating.
if peerKind == "group" && c.RequireMention() {
if !mentioned {
// Check if this message is in a thread where bot was previously mentioned.
inMentionedThread := false
if c.isThreadChannel(ctx, channelID) {
c.mentionedThreadsMu.Lock()
inMentionedThread = c.mentionedThreads[channelID]
c.mentionedThreadsMu.Unlock()
}

if mentioned {
// Track this thread so future messages don't need a mention.
if c.isThreadChannel(ctx, channelID) {
c.mentionedThreadsMu.Lock()
c.mentionedThreads[channelID] = true
// Cap to prevent unbounded growth
if len(c.mentionedThreads) > 5000 {
i := 0
for k := range c.mentionedThreads {
if i >= 2500 {
break
}
delete(c.mentionedThreads, k)
i++
}
}
c.mentionedThreadsMu.Unlock()
}
} else if !inMentionedThread {
// Collect media file paths for group history context.
var mediaPaths []string
for _, mf := range mediaFiles {
Expand Down