Skip to content

Commit 2a80198

Browse files
authored
feat(discord): add guild segmentation, DM support and context enrichment (#942)
1 parent 2217599 commit 2a80198

File tree

3 files changed

+69
-14
lines changed

3 files changed

+69
-14
lines changed

packages/server-shared/src/types/websocket/events.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface DiscordGuildMember {
99
export interface Discord {
1010
guildMember?: DiscordGuildMember
1111
guildId?: string
12+
guildName?: string
1213
channelId?: string
1314
}
1415

packages/stage-ui/src/stores/mods/api/context-bridge.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,11 @@ export const useContextBridgeStore = defineStore('mods:api:context-bridge', () =
9292
const chatProvider = await providersStore.getProviderInstance<ChatProvider>(activeProvider.value)
9393

9494
let messageText = text
95-
if (overrides?.messagePrefix)
95+
const targetSessionId = overrides?.sessionId
96+
97+
if (overrides?.messagePrefix) {
9698
messageText = `${overrides.messagePrefix}${text}`
99+
}
97100

98101
await chatOrchestrator.ingest(messageText, {
99102
model: activeModel.value,
@@ -108,7 +111,7 @@ export const useContextBridgeStore = defineStore('mods:api:context-bridge', () =
108111
contextUpdates: normalizedContextUpdates,
109112
},
110113
},
111-
}, overrides?.sessionId)
114+
}, targetSessionId)
112115
}
113116
}))
114117

services/discord-bot/src/adapters/airi-adapter.ts

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { env } from 'node:process'
66
import { useLogg } from '@guiiai/logg'
77
import { Client as AiriClient } from '@proj-airi/server-sdk'
88
import { ContextUpdateStrategy } from '@proj-airi/server-shared/types'
9-
import { Client, Events, GatewayIntentBits } from 'discord.js'
9+
import { Client, Events, GatewayIntentBits, Partials } from 'discord.js'
1010

1111
import { handlePing, registerCommands, VoiceManager } from '../bots/discord/commands'
1212

@@ -69,7 +69,9 @@ export class DiscordAdapter {
6969
GatewayIntentBits.GuildVoiceStates,
7070
GatewayIntentBits.GuildMessages,
7171
GatewayIntentBits.MessageContent,
72+
GatewayIntentBits.DirectMessages,
7273
],
74+
partials: [Partials.Channel],
7375
})
7476

7577
// Initialize AIRI client
@@ -162,7 +164,33 @@ export class DiscordAdapter {
162164
if (message?.content && discordContext?.channelId) {
163165
const channel = await this.discordClient.channels.fetch(discordContext.channelId)
164166
if (channel?.isTextBased() && 'send' in channel && typeof channel.send === 'function') {
165-
await channel.send(message.content)
167+
const content = message.content
168+
if (content.length <= 2000) {
169+
await channel.send(content)
170+
}
171+
else {
172+
let remaining = content
173+
while (remaining.length > 0) {
174+
let chunkSize = 2000
175+
if (remaining.length > 2000) {
176+
// Try to split at the last newline before 2000
177+
const lastNewline = remaining.lastIndexOf('\n', 2000)
178+
if (lastNewline > -1) {
179+
chunkSize = lastNewline
180+
}
181+
else {
182+
// Fallback to last space
183+
const lastSpace = remaining.lastIndexOf(' ', 2000)
184+
if (lastSpace > -1)
185+
chunkSize = lastSpace
186+
}
187+
}
188+
189+
const chunk = remaining.slice(0, chunkSize)
190+
await channel.send(chunk)
191+
remaining = remaining.slice(chunkSize).trim()
192+
}
193+
}
166194
}
167195
}
168196
}
@@ -183,18 +211,25 @@ export class DiscordAdapter {
183211
if (message.author.bot)
184212
return
185213

186-
// Respond if the bot is mentioned
187-
if (this.discordClient.user && message.mentions.has(this.discordClient.user)) {
214+
const isDM = !message.guild
215+
const isMentioned = this.discordClient.user && message.mentions.has(this.discordClient.user)
216+
217+
// Respond if the bot is mentioned OR if it's a DM
218+
if (isMentioned || isDM) {
188219
const rawContent = message.content
189-
const content = rawContent.replace(/<@!?\d+>/g, '').trim()
220+
const content = isMentioned
221+
? rawContent.replace(/<@!?\d+>/g, '').trim()
222+
: rawContent.trim()
223+
190224
if (!content)
191225
return
192226

193-
log.log(`Received text mention from ${message.author.tag} in ${message.channelId}`)
227+
log.log(`Received text message from ${message.author.tag} in ${isDM ? 'DM' : message.channelId}`)
194228

195229
const discordContext: Discord = {
196230
channelId: message.channelId,
197231
guildId: message.guildId ?? undefined,
232+
guildName: message.guild?.name ?? undefined,
198233
guildMember: {
199234
id: message.author.id,
200235
displayName: message.member?.displayName ?? message.author.username,
@@ -203,6 +238,22 @@ export class DiscordAdapter {
203238
}
204239
const normalizedDiscord = normalizeDiscordMetadata(discordContext)
205240
const displayName = normalizedDiscord?.guildMember?.displayName
241+
242+
// Enrich context and segment memory (moved from frontend)
243+
const serverName = normalizedDiscord?.guildName
244+
const contextPrefix = serverName
245+
? `on server '${serverName}'`
246+
: 'in Direct Message'
247+
248+
// Calculate sessionId based on guild or DM
249+
let targetSessionId = 'discord'
250+
if (normalizedDiscord?.guildId) {
251+
targetSessionId = `discord-guild-${normalizedDiscord.guildId}`
252+
}
253+
else {
254+
targetSessionId = `discord-dm-${normalizedDiscord?.guildMember?.id || 'unknown'}`
255+
}
256+
206257
const discordNotice = normalizedDiscord
207258
? `The input is coming from Discord channel ${normalizedDiscord.channelId} (Guild: ${normalizedDiscord.guildId ?? 'unknown'}).`
208259
: undefined
@@ -212,12 +263,12 @@ export class DiscordAdapter {
212263
data: {
213264
text: content,
214265
textRaw: rawContent,
215-
overrides: displayName
216-
? {
217-
messagePrefix: `(From Discord user ${displayName}): `,
218-
sessionId: 'discord',
219-
}
220-
: undefined,
266+
overrides: {
267+
messagePrefix: displayName
268+
? `(From Discord user ${displayName} ${contextPrefix}): `
269+
: `(From Discord user ${contextPrefix}): `,
270+
sessionId: targetSessionId,
271+
},
221272
contextUpdates: discordNotice
222273
? [{
223274
strategy: ContextUpdateStrategy.AppendSelf,

0 commit comments

Comments
 (0)