yao/agent/context/openapi_chat_test.go
Max 8dca4719c0 Remove deprecated agent API files and refactor agent loading logic
- Deleted obsolete agent API files (agent.go, api.go, api_test.go, types.go) to streamline the codebase.
- Refactored the agent loading logic to initialize the API instance correctly, ensuring proper integration with the new structure.
- Updated context handling to improve clarity and maintainability across the agent's functionality.
- Enhanced error handling and cache management in the agent's initialization process.
2025-11-11 11:23:20 +08:00

586 lines
14 KiB
Go

package context
import (
"bytes"
"encoding/json"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/yaoapp/gou/store"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/test"
)
func TestGetMessages_FromBody(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
gin.SetMode(gin.TestMode)
messages := []Message{
{
Role: RoleUser,
Content: "Hello, world!",
},
{
Role: RoleAssistant,
Content: "Hi there!",
},
}
requestBody := map[string]interface{}{
"messages": messages,
"model": "gpt-4",
}
bodyBytes, _ := json.Marshal(requestBody)
req := httptest.NewRequest("POST", "/chat/completions", bytes.NewBuffer(bodyBytes))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
result, err := GetMessages(c)
if err != nil {
t.Fatalf("Failed to get messages: %v", err)
}
if len(result) != 2 {
t.Errorf("Expected 2 messages, got %d", len(result))
}
if result[0].Role != RoleUser {
t.Errorf("Expected first message role to be %s, got %s", RoleUser, result[0].Role)
}
}
func TestGetMessages_FromQuery(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
gin.SetMode(gin.TestMode)
messages := []Message{
{
Role: RoleUser,
Content: "Test message",
},
}
messagesJSON, _ := json.Marshal(messages)
req := httptest.NewRequest("GET", "/chat/completions", nil)
q := req.URL.Query()
q.Add("messages", string(messagesJSON))
req.URL.RawQuery = q.Encode()
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
result, err := GetMessages(c)
if err != nil {
t.Fatalf("Failed to get messages: %v", err)
}
if len(result) != 1 {
t.Errorf("Expected 1 message, got %d", len(result))
}
}
func TestGetMessages_EmptyMessages(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
gin.SetMode(gin.TestMode)
requestBody := map[string]interface{}{
"messages": []Message{},
"model": "gpt-4",
}
bodyBytes, _ := json.Marshal(requestBody)
req := httptest.NewRequest("POST", "/chat/completions", bytes.NewBuffer(bodyBytes))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
_, err := GetMessages(c)
if err == nil {
t.Error("Expected error for empty messages")
}
}
func TestGetChatID_FromQuery(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
gin.SetMode(gin.TestMode)
cache, err := store.Get("__yao.agent.cache")
if err != nil {
t.Fatalf("Failed to get cache: %v", err)
}
expectedChatID := "test-chat-123"
req := httptest.NewRequest("GET", "/chat/completions?chat_id="+expectedChatID, nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
chatID, err := GetChatID(c, cache)
if err != nil {
t.Fatalf("Failed to get chat ID: %v", err)
}
if chatID != expectedChatID {
t.Errorf("Expected chat ID %s, got %s", expectedChatID, chatID)
}
}
func TestGetChatID_FromHeader(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
gin.SetMode(gin.TestMode)
cache, err := store.Get("__yao.agent.cache")
if err != nil {
t.Fatalf("Failed to get cache: %v", err)
}
expectedChatID := "header-chat-456"
req := httptest.NewRequest("GET", "/chat/completions", nil)
req.Header.Set("X-Yao-Chat", expectedChatID)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
chatID, err := GetChatID(c, cache)
if err != nil {
t.Fatalf("Failed to get chat ID: %v", err)
}
if chatID != expectedChatID {
t.Errorf("Expected chat ID %s, got %s", expectedChatID, chatID)
}
}
func TestGetChatID_FromMessages(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
gin.SetMode(gin.TestMode)
cache, err := store.Get("__yao.agent.cache")
if err != nil {
t.Fatalf("Failed to get cache: %v", err)
}
cache.Clear()
// First request with one user message
messages1 := []Message{
{
Role: RoleUser,
Content: "First message",
},
}
requestBody1 := map[string]interface{}{
"messages": messages1,
}
bodyBytes1, _ := json.Marshal(requestBody1)
req := httptest.NewRequest("POST", "/chat/completions", bytes.NewBuffer(bodyBytes1))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
chatID1, err := GetChatID(c, cache)
if err != nil {
t.Fatalf("Failed to get chat ID: %v", err)
}
if chatID1 == "" {
t.Error("Expected non-empty chat ID")
}
// Second request with two user messages (continuation)
messages2 := []Message{
{
Role: RoleUser,
Content: "First message",
},
{
Role: RoleUser,
Content: "Second message",
},
}
requestBody2 := map[string]interface{}{
"messages": messages2,
}
bodyBytes2, _ := json.Marshal(requestBody2)
req2 := httptest.NewRequest("POST", "/chat/completions", bytes.NewBuffer(bodyBytes2))
req2.Header.Set("Content-Type", "application/json")
w2 := httptest.NewRecorder()
c2, _ := gin.CreateTestContext(w2)
c2.Request = req2
chatID2, err := GetChatID(c2, cache)
if err != nil {
t.Fatalf("Failed to get chat ID second time: %v", err)
}
// Should get same chat ID (continuation of conversation)
if chatID1 != chatID2 {
t.Errorf("Expected same chat ID for continuation, got %s and %s", chatID1, chatID2)
}
}
func TestGetChatID_Priority(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
gin.SetMode(gin.TestMode)
cache, err := store.Get("__yao.agent.cache")
if err != nil {
t.Fatalf("Failed to get cache: %v", err)
}
queryChatID := "query-chat-id"
headerChatID := "header-chat-id"
messages := []Message{
{
Role: RoleUser,
Content: "This should not be used",
},
}
requestBody := map[string]interface{}{
"messages": messages,
}
bodyBytes, _ := json.Marshal(requestBody)
// Test priority: query > header > messages
req := httptest.NewRequest("POST", "/chat/completions?chat_id="+queryChatID, bytes.NewBuffer(bodyBytes))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Yao-Chat", headerChatID)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
chatID, err := GetChatID(c, cache)
if err != nil {
t.Fatalf("Failed to get chat ID: %v", err)
}
if chatID != queryChatID {
t.Errorf("Expected query parameter to take priority, got %s instead of %s", chatID, queryChatID)
}
}
func TestGetLocale_FromQuery(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?locale=zh-CN", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
locale := GetLocale(c)
if locale != "zh-cn" {
t.Errorf("Expected locale 'zh-cn', got '%s'", locale)
}
}
func TestGetLocale_FromHeader(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
req.Header.Set("Accept-Language", "en-US,en;q=0.9,zh;q=0.8")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
locale := GetLocale(c)
if locale != "en-us" {
t.Errorf("Expected locale 'en-us', got '%s'", locale)
}
}
func TestGetLocale_Priority(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?locale=fr-FR", nil)
req.Header.Set("Accept-Language", "en-US")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
locale := GetLocale(c)
if locale != "fr-fr" {
t.Errorf("Expected query parameter to take priority, got '%s'", locale)
}
}
func TestGetLocale_Empty(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
locale := GetLocale(c)
if locale != "" {
t.Errorf("Expected empty locale, got '%s'", locale)
}
}
func TestGetTheme_FromQuery(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?theme=dark", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
theme := GetTheme(c)
if theme != "dark" {
t.Errorf("Expected theme 'dark', got '%s'", theme)
}
}
func TestGetTheme_FromHeader(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
req.Header.Set("X-Yao-Theme", "light")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
theme := GetTheme(c)
if theme != "light" {
t.Errorf("Expected theme 'light', got '%s'", theme)
}
}
func TestGetTheme_Priority(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?theme=auto", nil)
req.Header.Set("X-Yao-Theme", "dark")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
theme := GetTheme(c)
if theme != "auto" {
t.Errorf("Expected query parameter to take priority, got '%s'", theme)
}
}
func TestGetTheme_Empty(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
theme := GetTheme(c)
if theme != "" {
t.Errorf("Expected empty theme, got '%s'", theme)
}
}
func TestGetReferer_FromQuery(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?referer=jssdk", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
referer := GetReferer(c)
if referer != "jssdk" {
t.Errorf("Expected referer 'jssdk', got '%s'", referer)
}
}
func TestGetReferer_FromHeader(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
req.Header.Set("X-Yao-Referer", "agent")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
referer := GetReferer(c)
if referer != "agent" {
t.Errorf("Expected referer 'agent', got '%s'", referer)
}
}
func TestGetReferer_Default(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
referer := GetReferer(c)
if referer != RefererAPI {
t.Errorf("Expected default referer '%s', got '%s'", RefererAPI, referer)
}
}
func TestGetReferer_InvalidValue(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?referer=invalid", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
referer := GetReferer(c)
if referer != RefererAPI {
t.Errorf("Expected default referer for invalid value, got '%s'", referer)
}
}
func TestGetReferer_Priority(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?referer=process", nil)
req.Header.Set("X-Yao-Referer", "tool")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
referer := GetReferer(c)
if referer != "process" {
t.Errorf("Expected query parameter to take priority, got '%s'", referer)
}
}
func TestGetAccept_FromQuery(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?accept=cui-web", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
accept := GetAccept(c)
if accept != AcceptWebCUI {
t.Errorf("Expected accept '%s', got '%s'", AcceptWebCUI, accept)
}
}
func TestGetAccept_FromHeader(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
req.Header.Set("X-Yao-Accept", "cui-native")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
accept := GetAccept(c)
if accept != AccepNativeCUI {
t.Errorf("Expected accept '%s', got '%s'", AccepNativeCUI, accept)
}
}
func TestGetAccept_FromUserAgent_Web(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
req.Header.Set("User-Agent", "Mozilla/5.0")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
accept := GetAccept(c)
if accept != AcceptWebCUI {
t.Errorf("Expected accept '%s' for web user agent, got '%s'", AcceptWebCUI, accept)
}
}
func TestGetAccept_FromUserAgent_Android(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
req.Header.Set("User-Agent", "Android App")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
accept := GetAccept(c)
if accept != AccepNativeCUI {
t.Errorf("Expected accept '%s' for Android, got '%s'", AccepNativeCUI, accept)
}
}
func TestGetAccept_FromUserAgent_Desktop(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions", nil)
req.Header.Set("User-Agent", "Windows NT 10.0")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
accept := GetAccept(c)
if accept != AcceptDesktopCUI {
t.Errorf("Expected accept '%s' for Windows, got '%s'", AcceptDesktopCUI, accept)
}
}
func TestGetAccept_Priority(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?accept=standard", nil)
req.Header.Set("X-Yao-Accept", "cui-web")
req.Header.Set("User-Agent", "Android App")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
accept := GetAccept(c)
if accept != AcceptStandard {
t.Errorf("Expected query parameter to take priority, got '%s'", accept)
}
}
func TestGetAccept_InvalidValue(t *testing.T) {
gin.SetMode(gin.TestMode)
req := httptest.NewRequest("GET", "/chat/completions?accept=invalid", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
accept := GetAccept(c)
if accept != AcceptStandard {
t.Errorf("Expected default accept for invalid value, got '%s'", accept)
}
}