fixes for bot-to-bot replie race condition
Some checks failed
Builds / Discord-Node-Build (push) Has been cancelled
Builds / Discord-Ollama-Container-Build (push) Has been cancelled
Coverage / Discord-Node-Coverage (push) Has been cancelled

This commit is contained in:
2025-05-21 17:30:09 -04:00
parent af8262455b
commit 9ffe94ad09
7 changed files with 127 additions and 41 deletions

View File

@@ -40,6 +40,16 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
const randomChance = Math.random() < 0.1 // 10% chance for non-directed or bot messages
if (!isMentioned && !isBotMessage && (isCommand || !randomChance)) return
// Check if message is a bot response to avoid loops
const isBotResponseKey = `message:${message.id}:is_bot_response`
if (isBotMessage) {
const isBotResponse = await redis.get(isBotResponseKey)
if (isBotResponse === 'true') {
log(`Skipping bot message ${message.id} as it is a bot response.`)
return
}
}
// Check cooldown for bot-to-bot responses
const botResponseCooldownKey = `bot:${clientId}:last_bot_response`
const cooldownPeriod = 60 // 60 seconds cooldown
@@ -105,7 +115,8 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
if (config === undefined) {
openConfig(`${message.author.username}-config.json`, 'message-style', false)
openConfig(`${message.author.username}-config.json`, 'switch-model', defaultModel)
reject(new Error('No User Preferences is set up.\n\nCreating preferences file with `message-style` set as `false` for regular message style.\nPlease try chatting again.'))
openConfig(`${message.author.username}-config.json`, 'modify-capacity', 50)
reject(new Error('No User Preferences is set up.\n\nCreating preferences file with defaults.\nPlease try chatting again.'))
return
}
@@ -113,7 +124,8 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
log(`New Capacity found. Setting Context Capacity to ${config.options['modify-capacity']}.`)
msgHist.capacity = config.options['modify-capacity']
} else {
log(`Capacity is undefined, using default capacity of ${msgHist.capacity}.`)
log(`Capacity is undefined, using default capacity of 50.`)
msgHist.capacity = 50
}
shouldStream = config.options['message-stream'] as boolean || false
@@ -137,29 +149,35 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
}
}
// Retrieve Channel Messages
let chatMessages: UserMessage[] = await new Promise((resolve) => {
getChannelInfo(`${message.channelId}-${message.author.username}.json`, (channelInfo) => {
if (channelInfo?.messages) {
resolve(channelInfo.messages)
} else {
log(`Channel/Thread ${message.channelId}-${message.author.username} does not exist. File will be created shortly...`)
resolve([])
}
})
})
if (chatMessages.length === 0) {
chatMessages = await new Promise((resolve, reject) => {
openChannelInfo(message.channelId, message.channel as TextChannel, message.author.tag)
getChannelInfo(`${message.channelId}-${message.author.username}.json`, (config) => {
if (config?.messages) {
resolve(config.messages)
} else {
reject(new Error(`Failed to find ${message.author.username}'s history. Try chatting again.`))
}
// Retrieve Channel Messages with Retry
let chatMessages: UserMessage[] = []
attempt = 0
while (attempt < maxRetries) {
try {
chatMessages = await new Promise((resolve, reject) => {
getChannelInfo(`${message.channelId}-${message.author.username}.json`, (channelInfo) => {
if (channelInfo?.messages) {
resolve(channelInfo.messages)
} else {
log(`Channel/Thread ${message.channelId}-${message.author.username} does not exist. Creating file...`)
openChannelInfo(message.channelId, message.channel as TextChannel, message.author.tag)
reject(new Error('Channel file created, retrying...'))
}
})
})
})
break
} catch (error) {
++attempt
if (attempt < maxRetries) {
log(`Attempt ${attempt} failed for Channel Info. Retrying in 500ms...`)
await new Promise(ret => setTimeout(ret, 500))
} else {
log(`Failed to retrieve or create channel history after ${maxRetries} attempts. Using empty history.`)
chatMessages = []
openChannelInfo(message.channelId, message.channel as TextChannel, message.author.tag, [])
break
}
}
}
if (!userConfig) {
@@ -334,9 +352,17 @@ export default event(Events.MessageCreate, async ({ log, msgHist, ollama, client
log(`Updated sentiments - Self: ${(jsonResponse.metadata.self_sentiment || 0).toFixed(2)}, User ${message.author.id}: ${(jsonResponse.metadata.user_sentiment[message.author.id] || 0).toFixed(2)}`)
}
// Send reply to Discord
// Send reply to Discord and mark as bot response
const reply = jsonResponse.reply || 'Sorry, I didnt get that. Can you try again?'
await message.reply(reply)
const replyMessage = await message.reply(reply)
if (isBotMessage) {
try {
await redis.set(`message:${replyMessage.id}:is_bot_response`, 'true', { EX: 3600 }) // 1 hour TTL
log(`Marked message ${replyMessage.id} as bot response`)
} catch (error) {
log(`Failed to mark message as bot response: ${error}`)
}
}
// Update message history
while (msgHist.size() >= msgHist.capacity) msgHist.dequeue()