Compare commits

...

1 Commits

Author SHA1 Message Date
Daisy Hollman
d01e0fbab2 fix(discord): use cached author.id when DMChannel.recipientId is null
DMChannel.recipientId can be null when client.channels.fetch() returns
a DM channel with a cold cache. The inbound gate correctly uses
msg.author.id, but fetchAllowedChannel relied on recipientId, so
replies to allowlisted DMs intermittently failed with "channel not
allowlisted" after session restart.

Maintain a channelId→userId map populated during inbound handling and
fall back to it when recipientId is null.

Fixes anthropics/claude-code#40576
Fixes anthropics/claude-code#41647

🏠 Remote-Dev: homespace
2026-04-12 03:58:34 +00:00

View File

@@ -222,6 +222,8 @@ type GateResult =
const recentSentIds = new Set<string>()
const RECENT_SENT_CAP = 200
const dmChannelUsers = new Map<string, string>()
function noteSent(id: string): void {
recentSentIds.add(id)
if (recentSentIds.size > RECENT_SENT_CAP) {
@@ -404,7 +406,8 @@ async function fetchAllowedChannel(id: string) {
const ch = await fetchTextChannel(id)
const access = loadAccess()
if (ch.type === ChannelType.DM) {
if (access.allowFrom.includes(ch.recipientId)) return ch
const userId = ch.recipientId ?? dmChannelUsers.get(id)
if (userId && access.allowFrom.includes(userId)) return ch
} else {
const key = ch.isThread() ? ch.parentId ?? ch.id : ch.id
if (key in access.groups) return ch
@@ -823,6 +826,10 @@ async function handleInbound(msg: Message): Promise<void> {
const chat_id = msg.channelId
if (msg.channel.type === ChannelType.DM) {
dmChannelUsers.set(chat_id, msg.author.id)
}
// Permission-reply intercept: if this looks like "yes xxxxx" for a
// pending permission request, emit the structured event instead of
// relaying as chat. The sender is already gate()-approved at this point