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 // }