fix(widget): match WhatsApp's conversation reuse/reopen semantics - #321
Open
mateusbellozupko wants to merge 1 commit into
Conversation
- base_controller#conversation: mirrors Whatsapp::IncomingMessageBaseService #set_conversation — when lock_to_single_conversation is on, always resume the contact's last conversation regardless of status; otherwise never resume a resolved one (a new conversation is created instead). - Conversation#bump_ai_session_epoch_if_reopened: bumps a counter in custom_attributes whenever a conversation is reopened after being resolved. - AgentBots::HttpRequestService#extract_context_id: folds that epoch into the AI processor's contextId, so a reopened conversation gets a fresh AI session (no more repeated "you're already in the queue"/"already transferred" replies) even when lock_to_single_conversation keeps every exchange in the same Chatwoot conversation thread (EVO-2241). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reviewer's GuideThe PR aligns widget conversation selection with WhatsApp-style lock and resolution semantics, then prevents stale AI session history from carrying across genuine resolved-to-open reopens by versioning the agent-bot contextId. Sequence diagram for fresh AI context after conversation reopensequenceDiagram
participant Widget
participant Conversation
participant AgentBot as AgentBots::HttpRequestService
participant AI as AI processor
Widget->>Conversation: update status from resolved to open/pending
Conversation-->>Conversation: bump_ai_session_epoch_if_reopened
Widget->>AgentBot: extract_context_id
AgentBot->>Conversation: read custom_attributes[ai_session_epoch]
Conversation-->>AgentBot: conversation UUID and reopen epoch
AgentBot->>AI: request with contextId conversation UUID plus _r epoch
AI-->>AgentBot: process as fresh ADK session
Flow diagram for widget conversation reuse and reopeningflowchart TD
A[Widget requests conversation] --> B{Inbox lock_to_single_conversation?}
B -->|Yes| C[Resume most recent conversation]
B -->|No| D[Find most recent non-resolved conversation]
D --> E{Conversation found?}
E -->|Yes| F[Reuse conversation]
E -->|No| G[Create new conversation]
C --> H{Conversation status resolved?}
H -->|Yes| I[Reopen conversation]
H -->|No| J[Continue conversation]
I --> K[bump_ai_session_epoch_if_reopened]
K --> L[Next bot request uses new contextId]
F --> J
G --> J
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've reviewed your changes and they look great!
Sourcery assessment
Needs a human reviewer. If the reuse or reopen logic is wrong, new messages could be attached to an incorrect existing conversation or continue with the wrong AI session context, and the epoch is persisted in conversation attributes. Reverting stops the new behavior, but messages and session records created under the wrong association would require bounded cleanup or replay.
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three related fixes, mirroring how
Whatsapp::IncomingMessageBaseService#set_conversationalready handles this:Api::V1::Widget::BaseController#conversation: previously always fell back to the contact's most recent conversation regardless of status, meaning a resolved widget conversation was silently reused/reopened forever, ignoring the inbox'slock_to_single_conversationsetting entirely (the widget controller never consulted it). Now: whenlock_to_single_conversationis on, resume the last conversation regardless of status (unchanged, matches WhatsApp locked behavior); when it's off, never resume a resolved one — a new conversation is created instead.Conversation#bump_ai_session_epoch_if_reopened: bumps a counter incustom_attributeswhenever a conversation transitions fromresolvedback to open/pending.AgentBots::HttpRequestService#extract_context_id: folds that epoch into the AI processor'scontextId(which is used to derive the ADK session id). Without this, a conversation kept alive vialock_to_single_conversation(or simply reopened before this PR's fix feat: Runtime Config — admin panel for system configurations #1) would carry forward the AI's full prior session history — so the bot kept repeating stale replies like "you're already in the queue" / "you were already transferred" instead of treating the reopened conversation as a fresh interaction.Testing notes
CONVERSATION_OPENED/status dirty-tracking hook fires correctly onresolved -> opentransitions specifically (notpending -> openor other transitions) viasaved_change_to_status?/status_before_last_save.contextIdis confirmed (viaextract_context_id's existing logic) to always be the conversation UUID, so folding in the epoch only changes it on genuine reopens, not on every message.🤖 Generated with Claude Code
Summary by Sourcery
Match widget conversation reuse and AI session behavior to WhatsApp semantics when conversations are reopened.
Bug Fixes:
Enhancements: