From 175c7ad2198872bd96e88b203f963848a912c617 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sun, 1 Mar 2026 11:33:11 -0500 Subject: [PATCH] fix: clean ||| from chat history and handle afterthoughts in reaction replies - Extract _split_afterthought helper method - Store cleaned content (no |||) in chat history to prevent LLM reinforcement - Handle afterthought splitting in reaction-reply path too - Log main_reply instead of raw response Co-Authored-By: Claude Opus 4.6 --- cogs/chat.py | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/cogs/chat.py b/cogs/chat.py index c031222..ec4ccdb 100644 --- a/cogs/chat.py +++ b/cogs/chat.py @@ -73,6 +73,19 @@ def _format_relative_time(dt: datetime) -> str: class ChatCog(commands.Cog): + + @staticmethod + def _split_afterthought(response: str) -> tuple[str, str | None]: + """Split a response on ||| into (main_reply, afterthought).""" + if "|||" not in response: + return response, None + parts = response.split("|||", 1) + main = parts[0].strip() + after = parts[1].strip() or None + if not main: + return response, None + return main, after + def __init__(self, bot: commands.Bot): self.bot = bot # Per-channel conversation history for the bot: {channel_id: deque of {role, content}} @@ -395,9 +408,14 @@ class ChatCog(commands.Cog): logger.warning("LLM returned no response for %s in #%s", message.author, message.channel.name) return + # Split afterthoughts (triple-pipe delimiter) + main_reply, afterthought = self._split_afterthought(response) + + # Store cleaned content in history (no ||| delimiter) if not image_attachment: + clean_for_history = f"{main_reply}\n{afterthought}" if afterthought else main_reply self._chat_history[ch_id].append( - {"role": "assistant", "content": response} + {"role": "assistant", "content": clean_for_history} ) # Reset proactive cooldown counter for this channel @@ -415,17 +433,6 @@ class ChatCog(commands.Cog): except (asyncio.TimeoutError, asyncio.CancelledError): pass - # Split afterthoughts (triple-pipe delimiter) - main_reply = response - afterthought = None - if "|||" in response: - parts = response.split("|||", 1) - main_reply = parts[0].strip() - afterthought = parts[1].strip() if len(parts) > 1 else None - if not main_reply: - main_reply = response - afterthought = None - await message.reply(main_reply, mention_author=False) if afterthought: @@ -446,7 +453,7 @@ class ChatCog(commands.Cog): reply_type.capitalize(), message.channel.name, message.author.display_name, - response[:100], + main_reply[:100], ) @@ -518,15 +525,22 @@ class ChatCog(commands.Cog): if not response: return - self._chat_history[ch_id].append({"role": "assistant", "content": response}) + main_reply, afterthought = self._split_afterthought(response) + clean_for_history = f"{main_reply}\n{afterthought}" if afterthought else main_reply + self._chat_history[ch_id].append({"role": "assistant", "content": clean_for_history}) + + await channel.send(main_reply) + + if afterthought: + await asyncio.sleep(random.uniform(2.0, 5.0)) + await channel.send(afterthought) - await channel.send(response) logger.info( "Reaction reply in #%s to %s (%s): %s", channel.name, member.display_name, emoji, - response[:100], + main_reply[:100], )