Assigning a conversation to an Agent Bot now moves it to pending. Assigning a bot-owned pending conversation to a human opens it again, while other assignment changes preserve the existing status. This makes existing Agent Bot ownership behave like an AI handoff without depending on the assignment dropdown UI work. Closes: https://linear.app/chatwoot/issue/CW-7448/apply-agent-bot-assignment-behavior ## Why Agent Bot ownership should remove conversations from the main open queue while the bot is handling them. Explicit human takeover should bring a bot-owned pending conversation back to the open queue and clear the bot owner. ## What changed - Agent Bot assignment clears the human assignee and marks the conversation pending. - Human assignment clears the Agent Bot owner and opens the conversation only when it was bot-owned and pending. - Ordinary human assignment, non-pending bot takeover, and unassignment preserve the existing conversation status. - Manual human takeover uses the existing assignment and status events. Bot-initiated handoffs continue to use the existing bot-handoff event path. ## Validation - Assign an open conversation to an Agent Bot through the assignment API and verify it becomes pending. - Assign that bot-owned pending conversation to a human and verify it becomes open. - Verify ordinary human assignment, non-pending bot takeover, and unassignment do not force a status change.
53 lines
1.3 KiB
Ruby
53 lines
1.3 KiB
Ruby
class Conversations::AssignmentService
|
|
def initialize(conversation:, assignee_id:, assignee_type: nil)
|
|
@conversation = conversation
|
|
@assignee_id = assignee_id
|
|
@assignee_type = assignee_type
|
|
end
|
|
|
|
def perform
|
|
agent_bot_assignment? ? assign_agent_bot : assign_agent
|
|
end
|
|
|
|
private
|
|
|
|
attr_reader :conversation, :assignee_id, :assignee_type
|
|
|
|
def assign_agent
|
|
conversation.with_lock do
|
|
if assignee.present? && conversation.assignee_agent_bot_id.present? && conversation.pending?
|
|
conversation.status = :open
|
|
conversation.waiting_since = Time.current if conversation.waiting_since.blank?
|
|
end
|
|
conversation.assignee = assignee
|
|
conversation.assignee_agent_bot = nil
|
|
conversation.save!
|
|
end
|
|
assignee
|
|
end
|
|
|
|
def assign_agent_bot
|
|
return unless agent_bot
|
|
|
|
conversation.with_lock do
|
|
conversation.assignee = nil
|
|
conversation.assignee_agent_bot = agent_bot
|
|
conversation.status = :pending
|
|
conversation.save!
|
|
end
|
|
agent_bot
|
|
end
|
|
|
|
def assignee
|
|
@assignee ||= conversation.account.users.find_by(id: assignee_id)
|
|
end
|
|
|
|
def agent_bot
|
|
@agent_bot ||= AgentBot.accessible_to(conversation.account).find_by(id: assignee_id)
|
|
end
|
|
|
|
def agent_bot_assignment?
|
|
assignee_type.to_s == 'AgentBot'
|
|
end
|
|
end
|