yao/agent/assistant/load_test.go
Max 95b2547c54 Refactor to decouple attachments, RAG, and AI assistant components.
- Deleted session-related functions (UserID, GuestID, UserRoles, UserOrGuestID) from the agent package to streamline the codebase.
- Removed RAG-related code and references, simplifying the agent's architecture.
- Updated API and load functions to reflect these changes, ensuring consistency across the agent module.
- Enhanced test coverage by cleaning up deprecated test cases related to removed functionalities.
2025-11-06 19:09:44 +08:00

435 lines
15 KiB
Go

package assistant
// func prepare(t *testing.T) {
// test.Prepare(t, config.Conf)
// }
// func TestLoad_LoadPath(t *testing.T) {
// prepare(t)
// defer test.Clean()
// assistant, err := LoadPath("/assistants/modi")
// if err != nil {
// t.Fatal(err)
// }
// // Validate basic properties
// assert.NotNil(t, assistant)
// assert.Equal(t, "modi", assistant.ID)
// assert.Equal(t, "Modi", assistant.Name)
// assert.Equal(t, "https://api.dicebear.com/7.x/bottts/svg?seed=Modi", assistant.Avatar)
// assert.Equal(t, "deepseek", assistant.Connector)
// assert.NotNil(t, assistant.Prompts)
// assert.NotNil(t, assistant.Script)
// // Test non-existent assistant
// _, err = LoadPath("/assistants/non-existent")
// assert.Error(t, err)
// }
// func TestLoad_LoadStore(t *testing.T) {
// prepare(t)
// defer test.Clean()
// // Test with nil storage
// _, err := LoadStore("test-id")
// assert.Error(t, err)
// assert.Contains(t, err.Error(), "storage is not set")
// // Setup mock storage
// mockStore := &mockStore{
// data: map[string]map[string]interface{}{
// "test-id": {
// "assistant_id": "test-id",
// "name": "Test Assistant",
// "avatar": "test-avatar",
// "connector": "gpt-3_5-turbo",
// },
// },
// }
// SetStorage(mockStore)
// defer SetStorage(nil)
// // Test loading from store
// assistant, err := LoadStore("test-id")
// assert.NoError(t, err)
// assert.NotNil(t, assistant)
// assert.Equal(t, "test-id", assistant.ID)
// assert.Equal(t, "Test Assistant", assistant.Name)
// assert.Equal(t, "test-avatar", assistant.Avatar)
// assert.Equal(t, "gpt-3_5-turbo", assistant.Connector)
// // Test cache functionality
// assistant2, err := LoadStore("test-id")
// assert.NoError(t, err)
// assert.Equal(t, assistant, assistant2) // Should be the same instance from cache
// // Test non-existent assistant
// _, err = LoadStore("non-existent")
// assert.Error(t, err)
// }
// func TestLoad_Cache(t *testing.T) {
// prepare(t)
// defer test.Clean()
// // Clear any existing cache first
// ClearCache()
// // Test cache operations
// SetCache(2) // Set small cache size for testing
// assert.Equal(t, 2, loaded.capacity, "Cache capacity should be 2")
// // Create test assistants
// assistant1 := &Assistant{ID: "id1", Name: "Assistant 1"}
// assistant2 := &Assistant{ID: "id2", Name: "Assistant 2"}
// assistant3 := &Assistant{ID: "id3", Name: "Assistant 3"}
// // Test Put and Get
// loaded.Put(assistant1)
// assert.Equal(t, 1, loaded.Len(), "Cache should have 1 item")
// loaded.Put(assistant2)
// assert.Equal(t, 2, loaded.Len(), "Cache should have 2 items")
// // Test cache hit
// cached, exists := loaded.Get("id1")
// assert.True(t, exists)
// assert.Equal(t, assistant1, cached)
// // Test cache eviction (LRU)
// // At this point: assistant1 is most recently used (due to Get), then assistant2
// loaded.Put(assistant3) // This should evict assistant2 since it's least recently used
// assert.Equal(t, 2, loaded.Len(), "Cache should still have 2 items")
// _, exists = loaded.Get("id2")
// assert.False(t, exists, "assistant2 should have been evicted (least recently used)")
// _, exists = loaded.Get("id1")
// assert.True(t, exists, "assistant1 should still be in cache (was accessed recently)")
// _, exists = loaded.Get("id3")
// assert.True(t, exists, "assistant3 should be in cache (most recently added)")
// // Test clear cache
// ClearCache()
// assert.Nil(t, loaded)
// // Test setting new cache capacity
// SetCache(100)
// assert.NotNil(t, loaded)
// }
// func TestLoad_Validate(t *testing.T) {
// tests := []struct {
// name string
// ast *Assistant
// wantErr bool
// }{
// {
// name: "valid assistant",
// ast: &Assistant{
// ID: "test-id",
// Name: "Test Assistant",
// Connector: "test-connector",
// },
// wantErr: false,
// },
// {
// name: "missing id",
// ast: &Assistant{
// Name: "Test Assistant",
// Connector: "test-connector",
// },
// wantErr: true,
// },
// {
// name: "missing name",
// ast: &Assistant{
// ID: "test-id",
// Connector: "test-connector",
// },
// wantErr: true,
// },
// {
// name: "missing connector",
// ast: &Assistant{
// ID: "test-id",
// Name: "Test Assistant",
// },
// wantErr: true,
// },
// }
// for _, tt := range tests {
// t.Run(tt.name, func(t *testing.T) {
// err := tt.ast.Validate()
// if (err != nil) != tt.wantErr {
// t.Errorf("Assistant.Validate() error = %v, wantErr %v", err, tt.wantErr)
// }
// })
// }
// }
// func TestLoad_Clone(t *testing.T) {
// // Create a test assistant with all fields populated
// original := &Assistant{
// ID: "test-id",
// Type: "test-type",
// Name: "Test Assistant",
// Avatar: "test-avatar",
// Connector: "test-connector",
// Path: "test-path",
// BuiltIn: true,
// Sort: 1,
// Description: "test description",
// Tags: []string{"tag1", "tag2"},
// Readonly: true,
// Mentionable: true,
// Automated: true,
// Options: map[string]interface{}{"key": "value"},
// Prompts: []Prompt{{Role: "system", Content: "test"}},
// Workflow: map[string]interface{}{"step": "test"},
// }
// // Clone the assistant
// clone := original.Clone()
// // Verify all fields are correctly cloned
// assert.Equal(t, original.ID, clone.ID)
// assert.Equal(t, original.Type, clone.Type)
// assert.Equal(t, original.Name, clone.Name)
// assert.Equal(t, original.Avatar, clone.Avatar)
// assert.Equal(t, original.Connector, clone.Connector)
// assert.Equal(t, original.Path, clone.Path)
// assert.Equal(t, original.BuiltIn, clone.BuiltIn)
// assert.Equal(t, original.Sort, clone.Sort)
// assert.Equal(t, original.Description, clone.Description)
// assert.Equal(t, original.Tags, clone.Tags)
// assert.Equal(t, original.Readonly, clone.Readonly)
// assert.Equal(t, original.Mentionable, clone.Mentionable)
// assert.Equal(t, original.Automated, clone.Automated)
// assert.Equal(t, original.Options, clone.Options)
// assert.Equal(t, original.Prompts, clone.Prompts)
// assert.Equal(t, original.Workflow, clone.Workflow)
// // Verify deep copy by modifying original
// original.Tags[0] = "modified"
// original.Options["key"] = "modified"
// original.Workflow["step"] = "modified"
// assert.NotEqual(t, original.Tags[0], clone.Tags[0])
// assert.NotEqual(t, original.Options["key"], clone.Options["key"])
// assert.NotEqual(t, original.Workflow["step"], clone.Workflow["step"])
// // Test nil case
// var nilAssistant *Assistant
// assert.Nil(t, nilAssistant.Clone())
// }
// func TestLoad_Update(t *testing.T) {
// // Create a test assistant
// ast := &Assistant{
// ID: "test-id",
// Name: "Original Name",
// Connector: "original-connector",
// }
// // Test updating various fields
// updates := map[string]interface{}{
// "name": "Updated Name",
// "avatar": "updated-avatar",
// "description": "Updated description",
// "connector": "updated-connector",
// "type": "updated-type",
// "sort": 2,
// "mentionable": true,
// "automated": true,
// "tags": []string{"new-tag"},
// "options": map[string]interface{}{"new": "value"},
// }
// err := ast.Update(updates)
// assert.NoError(t, err)
// // Verify updates
// assert.Equal(t, "Updated Name", ast.Name)
// assert.Equal(t, "updated-avatar", ast.Avatar)
// assert.Equal(t, "Updated description", ast.Description)
// assert.Equal(t, "updated-connector", ast.Connector)
// assert.Equal(t, "updated-type", ast.Type)
// assert.Equal(t, 2, ast.Sort)
// assert.True(t, ast.Mentionable)
// assert.True(t, ast.Automated)
// assert.Equal(t, []string{"new-tag"}, ast.Tags)
// assert.Equal(t, map[string]interface{}{"new": "value"}, ast.Options)
// // Test nil assistant
// var nilAssistant *Assistant
// err = nilAssistant.Update(updates)
// assert.Error(t, err)
// // Test invalid update that would make the assistant invalid
// invalidUpdates := map[string]interface{}{
// "name": "",
// }
// err = ast.Update(invalidUpdates)
// assert.Error(t, err)
// }
// func TestLoadBuiltIn(t *testing.T) {
// prepare(t)
// defer test.Clean()
// // Clear any existing cache and storage
// ClearCache()
// SetStorage(nil)
// // Create a mock store to verify built-in assistants are saved
// mockStore := &mockStore{
// data: make(map[string]map[string]interface{}),
// }
// SetStorage(mockStore)
// SetCache(100)
// // Test loading built-in assistants
// err := LoadBuiltIn()
// assert.NoError(t, err)
// // Verify Modi assistant was loaded
// assistant, exists := loaded.Get("modi")
// assert.True(t, exists, "Modi assistant should be loaded in cache")
// if exists {
// assert.Equal(t, "modi", assistant.ID)
// assert.Equal(t, "Modi", assistant.Name)
// assert.Equal(t, "deepseek", assistant.Connector)
// assert.True(t, assistant.BuiltIn)
// assert.True(t, assistant.Readonly)
// assert.NotNil(t, assistant.Prompts)
// assert.NotNil(t, assistant.Script)
// }
// }
// // mockStore implements store.Store interface for testing
// type mockStore struct {
// data map[string]map[string]interface{}
// }
// func (m *mockStore) GetAssistant(id string, locale ...string) (map[string]interface{}, error) {
// if data, ok := m.data[id]; ok {
// return data, nil
// }
// return nil, fmt.Errorf("assistant not found: %s", id)
// }
// // Add other required interface methods with empty implementations
// func (m *mockStore) GetThread(id string) (map[string]interface{}, error) { return nil, nil }
// func (m *mockStore) GetMessage(id string) (map[string]interface{}, error) { return nil, nil }
// func (m *mockStore) GetFile(id string) (map[string]interface{}, error) { return nil, nil }
// func (m *mockStore) CreateAssistant(data map[string]interface{}) (map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) CreateThread(data map[string]interface{}) (map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) CreateMessage(data map[string]interface{}) (map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) CreateFile(data map[string]interface{}) (map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) UpdateAssistant(id string, data map[string]interface{}) error { return nil }
// func (m *mockStore) UpdateThread(id string, data map[string]interface{}) error { return nil }
// func (m *mockStore) UpdateMessage(id string, data map[string]interface{}) error { return nil }
// func (m *mockStore) UpdateFile(id string, data map[string]interface{}) error { return nil }
// func (m *mockStore) DeleteAssistant(id string) error { return nil }
// func (m *mockStore) DeleteThread(id string) error { return nil }
// func (m *mockStore) DeleteMessage(id string) error { return nil }
// func (m *mockStore) DeleteFile(id string) error { return nil }
// func (m *mockStore) ListAssistants(query map[string]interface{}) ([]map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) ListThreads(query map[string]interface{}) ([]map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) ListMessages(query map[string]interface{}) ([]map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) ListFiles(query map[string]interface{}) ([]map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) DeleteAllChats(id string) error { return nil }
// func (m *mockStore) DeleteChat(id string, chatID string) error { return nil }
// func (m *mockStore) GetAssistants(filter store.AssistantFilter, locale ...string) (*store.AssistantResponse, error) {
// return nil, nil
// }
// func (m *mockStore) GetChat(id string, chatID string, locale ...string) (*store.ChatInfo, error) {
// return nil, nil
// }
// func (m *mockStore) GetChatWithFilter(id string, chatID string, filter store.ChatFilter, locale ...string) (*store.ChatInfo, error) {
// return nil, nil
// }
// func (m *mockStore) GetChats(id string, filter store.ChatFilter, locale ...string) (*store.ChatGroupResponse, error) {
// return nil, nil
// }
// func (m *mockStore) GetHistory(id string, chatID string, locale ...string) ([]map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) GetHistoryWithFilter(id string, chatID string, filter store.ChatFilter, locale ...string) ([]map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) SaveAssistant(assistant map[string]interface{}) (interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) SaveHistory(sid string, messages []map[string]interface{}, cid string, context map[string]interface{}) error {
// return nil
// }
// func (m *mockStore) UpdateChatTitle(sid string, cid string, title string) error { return nil }
// func (m *mockStore) DeleteAssistants(filter store.AssistantFilter) (int64, error) { return 0, nil }
// func (m *mockStore) GetAssistantTags(locale ...string) ([]store.Tag, error) {
// return []store.Tag{}, nil
// }
// // Attachment related methods
// func (m *mockStore) SaveAttachment(attachment map[string]interface{}) (interface{}, error) {
// return attachment["file_id"], nil
// }
// func (m *mockStore) DeleteAttachment(fileID string) error {
// return nil
// }
// func (m *mockStore) GetAttachments(filter store.AttachmentFilter, locale ...string) (*store.AttachmentResponse, error) {
// return &store.AttachmentResponse{}, nil
// }
// func (m *mockStore) GetAttachment(fileID string, locale ...string) (map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) DeleteAttachments(filter store.AttachmentFilter) (int64, error) {
// return 0, nil
// }
// // Knowledge related methods
// func (m *mockStore) SaveKnowledge(knowledge map[string]interface{}) (interface{}, error) {
// return knowledge["collection_id"], nil
// }
// func (m *mockStore) DeleteKnowledge(collectionID string) error {
// return nil
// }
// func (m *mockStore) GetKnowledges(filter store.KnowledgeFilter, locale ...string) (*store.KnowledgeResponse, error) {
// return &store.KnowledgeResponse{}, nil
// }
// func (m *mockStore) GetKnowledge(collectionID string, locale ...string) (map[string]interface{}, error) {
// return nil, nil
// }
// func (m *mockStore) DeleteKnowledges(filter store.KnowledgeFilter) (int64, error) {
// return 0, nil
// }
// // Close closes the store and releases any resources
// func (m *mockStore) Close() error {
// return nil
// }