Align GoChat with Chatwoot frontend contracts
This commit is contained in:
@@ -2,6 +2,7 @@ package v1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
|
||||
"github.com/gochat/gochat/internal/llm"
|
||||
"github.com/gochat/gochat/internal/model"
|
||||
"github.com/gochat/gochat/internal/repository"
|
||||
"github.com/gochat/gochat/internal/service"
|
||||
@@ -33,6 +35,10 @@ type copilotParityFixture struct {
|
||||
}
|
||||
|
||||
func newCopilotParityFixture(t *testing.T) *copilotParityFixture {
|
||||
return newCopilotParityFixtureWithProvider(t, nil)
|
||||
}
|
||||
|
||||
func newCopilotParityFixtureWithProvider(t *testing.T, provider llm.Provider) *copilotParityFixture {
|
||||
t.Helper()
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
@@ -66,7 +72,7 @@ func newCopilotParityFixture(t *testing.T) *copilotParityFixture {
|
||||
messageRepo := repository.NewCopilotMessageRepo(db)
|
||||
suggestionRepo := repository.NewCopilotSuggestionRepo(db)
|
||||
assistantRepo := repository.NewCaptainAssistantRepo(db)
|
||||
handler := NewCopilotHandler(service.NewCopilotService(threadRepo, messageRepo, suggestionRepo, nil, assistantRepo))
|
||||
handler := NewCopilotHandler(service.NewCopilotService(threadRepo, messageRepo, suggestionRepo, provider, assistantRepo))
|
||||
|
||||
fixture := &copilotParityFixture{
|
||||
db: db,
|
||||
@@ -237,6 +243,40 @@ func TestCopilotThreadMessagesListAndCreateUseNestedPayloads(t *testing.T) {
|
||||
require.Len(t, messages, 4)
|
||||
}
|
||||
|
||||
func TestCopilotThreadCreateProviderDisabledReturnsStableUnavailableAssistantMessage(t *testing.T) {
|
||||
f := newCopilotParityFixture(t)
|
||||
|
||||
thread := f.createThread(t, "Need help")
|
||||
threadID := uintString(uint(thread["id"].(float64)))
|
||||
w := f.request(f.router, http.MethodGet, f.captainPath("/copilot_threads/"+threadID+"/copilot_messages/"), nil)
|
||||
require.Equal(t, http.StatusOK, w.Code, w.Body.String())
|
||||
messages := decodeMap(t, w)["payload"].([]any)
|
||||
require.Len(t, messages, 2)
|
||||
assistant := messages[1].(map[string]any)
|
||||
require.Equal(t, "assistant", assistant["message_type"])
|
||||
require.Equal(t, service.CopilotUnavailableMessage, assistant["message"].(map[string]any)["content"])
|
||||
require.Nil(t, assistant["success"])
|
||||
}
|
||||
|
||||
func TestCopilotThreadCreateProviderEnabledPersistsGeneratedAssistantMessage(t *testing.T) {
|
||||
provider := &copilotFakeProvider{content: "Generated copilot answer"}
|
||||
f := newCopilotParityFixtureWithProvider(t, provider)
|
||||
|
||||
thread := f.createThread(t, "Need help")
|
||||
require.NotEmpty(t, provider.lastRequest.Messages)
|
||||
require.Equal(t, "system", provider.lastRequest.Messages[0].Role)
|
||||
require.Equal(t, "Need help", provider.lastRequest.Messages[len(provider.lastRequest.Messages)-1].Content)
|
||||
|
||||
threadID := uintString(uint(thread["id"].(float64)))
|
||||
w := f.request(f.router, http.MethodGet, f.captainPath("/copilot_threads/"+threadID+"/copilot_messages/"), nil)
|
||||
require.Equal(t, http.StatusOK, w.Code, w.Body.String())
|
||||
messages := decodeMap(t, w)["payload"].([]any)
|
||||
require.Len(t, messages, 2)
|
||||
assistant := messages[1].(map[string]any)
|
||||
require.Equal(t, "assistant", assistant["message_type"])
|
||||
require.Equal(t, "Generated copilot answer", assistant["message"].(map[string]any)["content"])
|
||||
}
|
||||
|
||||
func TestCopilotMessagePayloadUsesThreadPushShape(t *testing.T) {
|
||||
f := newCopilotParityFixture(t)
|
||||
thread := f.createThread(t, "Need help")
|
||||
@@ -312,3 +352,21 @@ func TestCopilotThreadGetAndDeleteAreScoped(t *testing.T) {
|
||||
w = f.request(f.router, http.MethodGet, path, nil)
|
||||
require.Equal(t, http.StatusNotFound, w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
type copilotFakeProvider struct {
|
||||
content string
|
||||
lastRequest llm.ChatRequest
|
||||
}
|
||||
|
||||
func (p *copilotFakeProvider) ChatCompletion(ctx context.Context, req llm.ChatRequest) (*llm.ChatResponse, error) {
|
||||
p.lastRequest = req
|
||||
return &llm.ChatResponse{Choices: []llm.ChatChoice{{Message: llm.ChatMessage{Role: "assistant", Content: p.content}}}}, nil
|
||||
}
|
||||
|
||||
func (p *copilotFakeProvider) CreateEmbedding(ctx context.Context, req llm.EmbeddingRequest) (*llm.EmbeddingResponse, error) {
|
||||
return &llm.EmbeddingResponse{}, nil
|
||||
}
|
||||
|
||||
func (p *copilotFakeProvider) ChatCompletionStream(ctx context.Context, req llm.ChatRequest, onChunk func(llm.StreamChunk) error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user