feat(conversations): complete manual AI takeover
This commit is contained in:
@@ -93,6 +93,7 @@ func (h *AssignableAgentHandler) List(c *gin.Context) {
|
||||
bot["assignee_type"] = "AgentBot"
|
||||
bot["icon"] = "i-lucide-bot"
|
||||
bot["availability_status"] = "offline"
|
||||
bot["confirmed"] = true
|
||||
payload = append(payload, bot)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1059,9 +1059,10 @@ func (h *ConversationHandler) AssignTeam(c *gin.Context) {
|
||||
}
|
||||
|
||||
var req struct {
|
||||
AgentID *uint `json:"agent_id"`
|
||||
AssigneeID *uint `json:"assignee_id"`
|
||||
TeamID *uint `json:"team_id"`
|
||||
AgentID *uint `json:"agent_id"`
|
||||
AssigneeID *uint `json:"assignee_id"`
|
||||
AssigneeType string `json:"assignee_type"`
|
||||
TeamID *uint `json:"team_id"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
|
||||
@@ -1076,6 +1077,23 @@ func (h *ConversationHandler) AssignTeam(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if req.AssigneeType == "AgentBot" {
|
||||
if agentID == nil {
|
||||
agentID = new(uint)
|
||||
}
|
||||
conversation, bot, svcErr := h.conversationSvc.AssignAgentBot(c.Request.Context(), accountID, conversation.ID, *agentID)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
recordAuditMutation(c, h.auditSvc, auditMutation{AccountID: accountID, AuditableType: "Conversation", AuditableID: conversation.ID, Action: "update", AuditedChanges: gin.H{"assignee_agent_bot_id": conversation.AssigneeAgentBotID}})
|
||||
if bot == nil {
|
||||
c.JSON(http.StatusOK, nil)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, serializeAgentBotSlim(bot))
|
||||
return
|
||||
}
|
||||
conversation, svcErr := h.conversationSvc.AssignTeam(c.Request.Context(), accountID, conversation.ID, agentID, req.TeamID)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
|
||||
@@ -732,7 +732,7 @@ func (s *ConversationCrudTestSuite) TestAssignAgentBot_MutuallyExclusiveAndAccou
|
||||
s.Require().NoError(s.db.Create(bot).Error)
|
||||
body, _ := json.Marshal(map[string]any{"assignee_id": bot.ID, "assignee_type": "AgentBot"})
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodPost, s.convURL(s.testConv.ID)+"/assign", bytes.NewReader(body))
|
||||
req := httptest.NewRequest(http.MethodPost, s.convURL(s.testConv.ID)+"/assignments", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
s.router.ServeHTTP(w, req)
|
||||
s.Equal(http.StatusOK, w.Code, w.Body.String())
|
||||
@@ -741,6 +741,21 @@ func (s *ConversationCrudTestSuite) TestAssignAgentBot_MutuallyExclusiveAndAccou
|
||||
s.Nil(assigned.AssigneeID)
|
||||
s.Require().NotNil(assigned.AssigneeAgentBotID)
|
||||
s.Equal(bot.ID, *assigned.AssigneeAgentBotID)
|
||||
s.Equal(string(model.ConversationStatusPending), assigned.Status)
|
||||
var assignmentResponse map[string]any
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &assignmentResponse))
|
||||
s.Equal("AgentBot", assignmentResponse["assignee_type"])
|
||||
|
||||
// Repeating takeover is idempotent.
|
||||
w = httptest.NewRecorder()
|
||||
req = httptest.NewRequest(http.MethodPost, s.convURL(s.testConv.ID)+"/assignments", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
s.router.ServeHTTP(w, req)
|
||||
s.Equal(http.StatusOK, w.Code, w.Body.String())
|
||||
s.Require().NoError(s.db.First(&assigned, s.testConv.ID).Error)
|
||||
s.Require().NotNil(assigned.AssigneeAgentBotID)
|
||||
s.Equal(bot.ID, *assigned.AssigneeAgentBotID)
|
||||
s.Equal(string(model.ConversationStatusPending), assigned.Status)
|
||||
|
||||
user := &model.User{Name: "Agent", Email: "bot-switch@example.com"}
|
||||
s.Require().NoError(s.db.Create(user).Error)
|
||||
@@ -756,6 +771,7 @@ func (s *ConversationCrudTestSuite) TestAssignAgentBot_MutuallyExclusiveAndAccou
|
||||
s.Require().NotNil(assigned.AssigneeID)
|
||||
s.Equal(user.ID, *assigned.AssigneeID)
|
||||
s.Nil(assigned.AssigneeAgentBotID)
|
||||
s.Equal(string(model.ConversationStatusOpen), assigned.Status)
|
||||
|
||||
other := &model.Account{Name: "Other"}
|
||||
s.Require().NoError(s.db.Create(other).Error)
|
||||
|
||||
@@ -767,12 +767,13 @@ func serializeCaptainAssistantSender(assistant *model.CaptainAssistant) map[stri
|
||||
|
||||
func serializeAgentBotSlim(bot *model.AgentBot) map[string]any {
|
||||
return map[string]any{
|
||||
"id": bot.ID,
|
||||
"name": bot.Name,
|
||||
"description": bot.Description,
|
||||
"thumbnail": bot.AvatarURL,
|
||||
"outgoing_url": bot.OutgoingURL,
|
||||
"bot_type": bot.BotType,
|
||||
"id": bot.ID,
|
||||
"name": bot.Name,
|
||||
"description": bot.Description,
|
||||
"thumbnail": bot.AvatarURL,
|
||||
"outgoing_url": bot.OutgoingURL,
|
||||
"bot_type": bot.BotType,
|
||||
"assignee_type": "AgentBot",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user