feat(realtime): complete fake channel reply flow
This commit is contained in:
@@ -4,12 +4,14 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/gochat/gochat/internal/llm"
|
||||
"github.com/gochat/gochat/internal/model"
|
||||
"github.com/gochat/gochat/internal/service"
|
||||
"github.com/gochat/gochat/pkg/pagination"
|
||||
@@ -1055,6 +1057,29 @@ func handleServiceError(c *gin.Context, err error) {
|
||||
return
|
||||
}
|
||||
errMsg := err.Error()
|
||||
if errors.Is(err, llm.ErrProviderNotConfigured) {
|
||||
response.AbortWithStatusError(c, http.StatusServiceUnavailable, response.ErrCopilotNotConfigured, errMsg)
|
||||
return
|
||||
}
|
||||
var providerErr *llm.APIError
|
||||
if errors.As(err, &providerErr) {
|
||||
switch providerErr.StatusCode {
|
||||
case http.StatusUnauthorized, http.StatusForbidden:
|
||||
response.AbortWithStatusError(c, http.StatusBadGateway, response.ErrCopilotProviderAuth, "Copilot provider authentication failed")
|
||||
case http.StatusNotFound:
|
||||
response.AbortWithStatusError(c, http.StatusBadGateway, response.ErrCopilotModelNotFound, "Copilot provider endpoint or model was not found")
|
||||
case http.StatusTooManyRequests:
|
||||
response.AbortWithStatusError(c, http.StatusTooManyRequests, response.ErrCopilotProviderRateLimited, "Copilot provider rate limit exceeded")
|
||||
default:
|
||||
response.AbortWithStatusError(c, http.StatusBadGateway, response.ErrCopilotProviderUnreachable, "Copilot provider request failed")
|
||||
}
|
||||
return
|
||||
}
|
||||
var networkErr net.Error
|
||||
if errors.Is(err, context.DeadlineExceeded) || (errors.As(err, &networkErr) && networkErr.Timeout()) {
|
||||
response.AbortWithStatusError(c, http.StatusGatewayTimeout, response.ErrCopilotProviderTimeout, "Copilot provider request timed out")
|
||||
return
|
||||
}
|
||||
lower := strings.ToLower(errMsg)
|
||||
if strings.Contains(lower, "not found") || strings.Contains(lower, "record not found") {
|
||||
response.AbortWithStatusError(c, http.StatusNotFound, response.ErrNotFound, errMsg)
|
||||
|
||||
@@ -694,6 +694,7 @@ func serializeContactWithContext(ctx context.Context, contact *model.Contact) ma
|
||||
"custom_attributes": jsonObject(contact.CustomAttributes),
|
||||
"last_activity_at": int64Value(contact.LastActivityAt),
|
||||
"created_at": contact.CreatedAt.Unix(),
|
||||
"type": "contact",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,6 +711,7 @@ func serializeUser(user *model.User, accountID uint) map[string]any {
|
||||
"name": user.Name,
|
||||
"role": nonEmpty(user.Role, "agent"),
|
||||
"thumbnail": user.AvatarURL,
|
||||
"type": "user",
|
||||
}
|
||||
if attrs := jsonObject(user.CustomAttributes); len(attrs) > 0 {
|
||||
payload["custom_attributes"] = attrs
|
||||
|
||||
@@ -390,9 +390,19 @@ func TestSerializeContactUsesPresenceStatus(t *testing.T) {
|
||||
payload := serializeContactWithContext(ctx, contact)
|
||||
|
||||
require.Equal(t, "online", payload["availability_status"])
|
||||
require.Equal(t, "contact", payload["type"])
|
||||
require.Equal(t, "offline", serializeContact(contact)["availability_status"])
|
||||
}
|
||||
|
||||
func TestSerializeUserIncludesSenderType(t *testing.T) {
|
||||
user := &model.User{AccountID: 7, Name: "Support Agent"}
|
||||
user.ID = 43
|
||||
|
||||
payload := serializeUser(user, user.AccountID)
|
||||
|
||||
require.Equal(t, "user", payload["type"])
|
||||
}
|
||||
|
||||
func TestSerializeCRMContactUsesPresenceStatus(t *testing.T) {
|
||||
contact := &model.Contact{AccountID: 9, Name: "CRM Online Contact"}
|
||||
contact.ID = 99
|
||||
|
||||
Reference in New Issue
Block a user