Merge pull request #1281 from trheyi/main
Implement filtering for assistant tags retrieval
This commit is contained in:
commit
152f339252
9 changed files with 526 additions and 21 deletions
46
agent/api.go
46
agent/api.go
|
|
@ -1003,19 +1003,49 @@ func (agent *DSL) handleConnectors(c *gin.Context) {
|
||||||
|
|
||||||
// HandleAssistantTags handles getting all assistant tags (exported for use in openapi/agent)
|
// HandleAssistantTags handles getting all assistant tags (exported for use in openapi/agent)
|
||||||
func (agent *DSL) HandleAssistantTags(c *gin.Context) {
|
func (agent *DSL) HandleAssistantTags(c *gin.Context) {
|
||||||
sid := c.GetString("__sid")
|
|
||||||
if sid == "" {
|
|
||||||
c.JSON(400, gin.H{"message": "sid is required", "code": 400})
|
|
||||||
c.Done()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
locale := "en-us" // Default locale
|
locale := "en-us" // Default locale
|
||||||
if loc := c.Query("locale"); loc != "" {
|
if loc := c.Query("locale"); loc != "" {
|
||||||
locale = strings.ToLower(strings.TrimSpace(loc))
|
locale = strings.ToLower(strings.TrimSpace(loc))
|
||||||
}
|
}
|
||||||
|
|
||||||
tags, err := agent.Store.GetAssistantTags(locale)
|
// Build filter for tags query
|
||||||
|
filter := store.AssistantFilter{}
|
||||||
|
|
||||||
|
// Apply type filter (default to "assistant")
|
||||||
|
typeParam := strings.TrimSpace(c.Query("type"))
|
||||||
|
if typeParam == "" {
|
||||||
|
typeParam = "assistant"
|
||||||
|
}
|
||||||
|
filter.Type = typeParam
|
||||||
|
|
||||||
|
// Apply other optional filters
|
||||||
|
if connector := strings.TrimSpace(c.Query("connector")); connector != "" {
|
||||||
|
filter.Connector = connector
|
||||||
|
}
|
||||||
|
|
||||||
|
if builtInParam := c.Query("built_in"); builtInParam != "" {
|
||||||
|
if val, err := strconv.ParseBool(builtInParam); err == nil {
|
||||||
|
filter.BuiltIn = &val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if mentionableParam := c.Query("mentionable"); mentionableParam != "" {
|
||||||
|
if val, err := strconv.ParseBool(mentionableParam); err == nil {
|
||||||
|
filter.Mentionable = &val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if automatedParam := c.Query("automated"); automatedParam != "" {
|
||||||
|
if val, err := strconv.ParseBool(automatedParam); err == nil {
|
||||||
|
filter.Automated = &val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if keywords := strings.TrimSpace(c.Query("keywords")); keywords != "" {
|
||||||
|
filter.Keywords = keywords
|
||||||
|
}
|
||||||
|
|
||||||
|
tags, err := agent.Store.GetAssistantTags(filter, locale)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@ func (m *Mongo) DeleteAssistants(filter types.AssistantFilter) (int64, error) {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAssistantTags retrieves all unique tags from assistants
|
// GetAssistantTags retrieves all unique tags from assistants with filtering
|
||||||
func (m *Mongo) GetAssistantTags(locale ...string) ([]types.Tag, error) {
|
func (m *Mongo) GetAssistantTags(filter types.AssistantFilter, locale ...string) ([]types.Tag, error) {
|
||||||
return []types.Tag{}, nil
|
return []types.Tag{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@ func (r *Redis) DeleteAssistants(filter types.AssistantFilter) (int64, error) {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAssistantTags retrieves all unique tags from assistants
|
// GetAssistantTags retrieves all unique tags from assistants with filtering
|
||||||
func (r *Redis) GetAssistantTags(locale ...string) ([]types.Tag, error) {
|
func (r *Redis) GetAssistantTags(filter types.AssistantFilter, locale ...string) ([]types.Tag, error) {
|
||||||
return []types.Tag{}, nil
|
return []types.Tag{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,11 @@ type Store interface {
|
||||||
// Returns: Paginated assistant list and potential error
|
// Returns: Paginated assistant list and potential error
|
||||||
GetAssistants(filter AssistantFilter, locale ...string) (*AssistantList, error)
|
GetAssistants(filter AssistantFilter, locale ...string) (*AssistantList, error)
|
||||||
|
|
||||||
// GetAssistantTags retrieves all unique tags from assistants
|
// GetAssistantTags retrieves all unique tags from assistants with filtering
|
||||||
|
// filter: Filter conditions including QueryFilter for permission filtering
|
||||||
|
// locale: Optional locale for i18n translations
|
||||||
// Returns: List of tags and potential error
|
// Returns: List of tags and potential error
|
||||||
GetAssistantTags(locale ...string) ([]Tag, error)
|
GetAssistantTags(filter AssistantFilter, locale ...string) ([]Tag, error)
|
||||||
|
|
||||||
// GetAssistant retrieves a single assistant by ID
|
// GetAssistant retrieves a single assistant by ID
|
||||||
// assistantID: Assistant ID
|
// assistantID: Assistant ID
|
||||||
|
|
|
||||||
|
|
@ -544,10 +544,48 @@ func (conv *Xun) DeleteAssistants(filter types.AssistantFilter) (int64, error) {
|
||||||
return qb.Delete()
|
return qb.Delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAssistantTags retrieves all unique tags from assistants
|
// GetAssistantTags retrieves all unique tags from assistants with filtering
|
||||||
func (conv *Xun) GetAssistantTags(locale ...string) ([]types.Tag, error) {
|
func (conv *Xun) GetAssistantTags(filter types.AssistantFilter, locale ...string) ([]types.Tag, error) {
|
||||||
q := conv.newQuery().Table(conv.getAssistantTable())
|
qb := conv.query.New().Table(conv.getAssistantTable())
|
||||||
rows, err := q.Select("tags").Where("type", "assistant").GroupBy("tags").Get()
|
|
||||||
|
// Apply type filter (default to "assistant")
|
||||||
|
typeFilter := "assistant"
|
||||||
|
if filter.Type != "" {
|
||||||
|
typeFilter = filter.Type
|
||||||
|
}
|
||||||
|
qb.Where("type", typeFilter)
|
||||||
|
|
||||||
|
// Apply custom query filter function (for permission filtering)
|
||||||
|
if filter.QueryFilter != nil {
|
||||||
|
qb.Where(filter.QueryFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply other filters if provided
|
||||||
|
if filter.Connector != "" {
|
||||||
|
qb.Where("connector", filter.Connector)
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.BuiltIn != nil {
|
||||||
|
qb.Where("built_in", *filter.BuiltIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.Mentionable != nil {
|
||||||
|
qb.Where("mentionable", *filter.Mentionable)
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.Automated != nil {
|
||||||
|
qb.Where("automated", *filter.Automated)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply keyword filter if provided
|
||||||
|
if filter.Keywords != "" {
|
||||||
|
qb.Where(func(qb query.Query) {
|
||||||
|
qb.Where("name", "like", fmt.Sprintf("%%%s%%", filter.Keywords)).
|
||||||
|
OrWhere("description", "like", fmt.Sprintf("%%%s%%", filter.Keywords))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := qb.Select("tags").GroupBy("tags").Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -803,7 +803,7 @@ func TestGetAssistantTags(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all tags
|
// Get all tags
|
||||||
tags, err := store.GetAssistantTags()
|
tags, err := store.GetAssistantTags(types.AssistantFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get tags: %v", err)
|
t.Fatalf("Failed to get tags: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -825,6 +825,167 @@ func TestGetAssistantTags(t *testing.T) {
|
||||||
|
|
||||||
t.Logf("Found %d unique tags", len(tags))
|
t.Logf("Found %d unique tags", len(tags))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("GetTagsWithFilter", func(t *testing.T) {
|
||||||
|
// Create test assistants with specific tags and attributes
|
||||||
|
uniqueTag := fmt.Sprintf("filter-tag-%d", time.Now().UnixNano())
|
||||||
|
assistants := []types.AssistantModel{
|
||||||
|
{
|
||||||
|
Name: "Filtered Tags Test 1",
|
||||||
|
Type: "assistant",
|
||||||
|
Connector: "openai",
|
||||||
|
Tags: []string{uniqueTag, "ai"},
|
||||||
|
Share: "private",
|
||||||
|
BuiltIn: false,
|
||||||
|
Mentionable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Filtered Tags Test 2",
|
||||||
|
Type: "assistant",
|
||||||
|
Connector: "anthropic",
|
||||||
|
Tags: []string{uniqueTag, "coding"},
|
||||||
|
Share: "private",
|
||||||
|
BuiltIn: true,
|
||||||
|
Mentionable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Filtered Tags Test 3",
|
||||||
|
Type: "assistant",
|
||||||
|
Connector: "openai",
|
||||||
|
Tags: []string{uniqueTag, "search"},
|
||||||
|
Share: "private",
|
||||||
|
BuiltIn: false,
|
||||||
|
Automated: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, asst := range assistants {
|
||||||
|
_, err := store.SaveAssistant(&asst)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create assistant: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: Get tags filtered by connector
|
||||||
|
tagsOpenAI, err := store.GetAssistantTags(types.AssistantFilter{
|
||||||
|
Connector: "openai",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get tags with connector filter: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Found %d tags for openai connector", len(tagsOpenAI))
|
||||||
|
|
||||||
|
// Test: Get tags filtered by built_in
|
||||||
|
builtInFalse := false
|
||||||
|
tagsNonBuiltIn, err := store.GetAssistantTags(types.AssistantFilter{
|
||||||
|
BuiltIn: &builtInFalse,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get tags with built_in filter: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Found %d tags for non-built-in assistants", len(tagsNonBuiltIn))
|
||||||
|
|
||||||
|
// Test: Get tags filtered by mentionable
|
||||||
|
mentionableTrue := true
|
||||||
|
tagsMentionable, err := store.GetAssistantTags(types.AssistantFilter{
|
||||||
|
Mentionable: &mentionableTrue,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get tags with mentionable filter: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Found %d tags for mentionable assistants", len(tagsMentionable))
|
||||||
|
|
||||||
|
// Test: Get tags filtered by keywords
|
||||||
|
tagsWithKeywords, err := store.GetAssistantTags(types.AssistantFilter{
|
||||||
|
Keywords: "Filtered Tags Test",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get tags with keywords filter: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Found %d tags with keywords filter", len(tagsWithKeywords))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("GetTagsWithQueryFilter", func(t *testing.T) {
|
||||||
|
// Create test assistants with permission fields
|
||||||
|
permTag := fmt.Sprintf("perm-tag-%d", time.Now().UnixNano())
|
||||||
|
assistants := []types.AssistantModel{
|
||||||
|
{
|
||||||
|
Name: "Permission Tags Test 1",
|
||||||
|
Type: "assistant",
|
||||||
|
Connector: "openai",
|
||||||
|
Tags: []string{permTag, "public-tag"},
|
||||||
|
Share: "private",
|
||||||
|
Public: true,
|
||||||
|
YaoCreatedBy: "user-1",
|
||||||
|
YaoTeamID: "team-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Permission Tags Test 2",
|
||||||
|
Type: "assistant",
|
||||||
|
Connector: "openai",
|
||||||
|
Tags: []string{permTag, "team-tag"},
|
||||||
|
Share: "team",
|
||||||
|
Public: false,
|
||||||
|
YaoCreatedBy: "user-2",
|
||||||
|
YaoTeamID: "team-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Permission Tags Test 3",
|
||||||
|
Type: "assistant",
|
||||||
|
Connector: "openai",
|
||||||
|
Tags: []string{permTag, "private-tag"},
|
||||||
|
Share: "private",
|
||||||
|
Public: false,
|
||||||
|
YaoCreatedBy: "user-3",
|
||||||
|
YaoTeamID: "team-2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, asst := range assistants {
|
||||||
|
_, err := store.SaveAssistant(&asst)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create assistant: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: Get tags for public assistants only
|
||||||
|
tagsPublic, err := store.GetAssistantTags(types.AssistantFilter{
|
||||||
|
QueryFilter: func(qb query.Query) {
|
||||||
|
qb.Where("public", true)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get tags for public assistants: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Found %d tags for public assistants", len(tagsPublic))
|
||||||
|
|
||||||
|
// Test: Get tags for team-1 assistants
|
||||||
|
tagsTeam1, err := store.GetAssistantTags(types.AssistantFilter{
|
||||||
|
QueryFilter: func(qb query.Query) {
|
||||||
|
qb.Where("__yao_team_id", "team-1")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get tags for team-1: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Found %d tags for team-1 assistants", len(tagsTeam1))
|
||||||
|
|
||||||
|
// Test: Complex permission filter (public OR team-1 with share=team)
|
||||||
|
tagsComplex, err := store.GetAssistantTags(types.AssistantFilter{
|
||||||
|
QueryFilter: func(qb query.Query) {
|
||||||
|
qb.Where(func(qb query.Query) {
|
||||||
|
qb.Where("public", true)
|
||||||
|
}).OrWhere(func(qb query.Query) {
|
||||||
|
qb.Where("__yao_team_id", "team-1").
|
||||||
|
Where("share", "team")
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get tags with complex filter: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Found %d tags with complex permission filter", len(tagsComplex))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGenerateAssistantID tests the ID generation function
|
// TestGenerateAssistantID tests the ID generation function
|
||||||
|
|
@ -1672,7 +1833,7 @@ func TestAssistantCompleteWorkflow(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5: Get tags
|
// Step 5: Get tags
|
||||||
tags, err := store.GetAssistantTags()
|
tags, err := store.GetAssistantTags(types.AssistantFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get tags: %v", err)
|
t.Fatalf("Failed to get tags: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ func Attach(group *gin.RouterGroup, oauth types.OAuth) {
|
||||||
// Assistant CRUD - Standard REST endpoints
|
// Assistant CRUD - Standard REST endpoints
|
||||||
assistants.GET("/", ListAssistants) // GET /assistants - List assistants
|
assistants.GET("/", ListAssistants) // GET /assistants - List assistants
|
||||||
assistants.POST("/", n.HandleAssistantSave) // POST /assistants - Create/Update assistant
|
assistants.POST("/", n.HandleAssistantSave) // POST /assistants - Create/Update assistant
|
||||||
assistants.GET("/tags", n.HandleAssistantTags) // GET /assistants/tags - Get all assistant tags
|
assistants.GET("/tags", ListAssistantTags) // GET /assistants/tags - Get all assistant tags with permission filtering
|
||||||
assistants.GET("/:id", n.HandleAssistantDetail) // GET /assistants/:id - Get assistant details
|
assistants.GET("/:id", n.HandleAssistantDetail) // GET /assistants/:id - Get assistant details
|
||||||
assistants.DELETE("/:id", n.HandleAssistantDelete) // DELETE /assistants/:id - Delete assistant
|
assistants.DELETE("/:id", n.HandleAssistantDelete) // DELETE /assistants/:id - Delete assistant
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -159,3 +159,77 @@ func ListAssistants(c *gin.Context) {
|
||||||
// Return the result with standard response format
|
// Return the result with standard response format
|
||||||
response.RespondWithSuccess(c, response.StatusOK, result)
|
response.RespondWithSuccess(c, response.StatusOK, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListAssistantTags lists assistant tags with permission-based filtering
|
||||||
|
func ListAssistantTags(c *gin.Context) {
|
||||||
|
|
||||||
|
// Get authorized information
|
||||||
|
authInfo := authorized.GetInfo(c)
|
||||||
|
|
||||||
|
// Get Agent instance from global variable
|
||||||
|
agentInstance := agent.GetAgent()
|
||||||
|
if agentInstance == nil || agentInstance.Store == nil {
|
||||||
|
errorResp := &response.ErrorResponse{
|
||||||
|
Code: response.ErrServerError.Code,
|
||||||
|
ErrorDescription: "Agent store not initialized",
|
||||||
|
}
|
||||||
|
response.RespondWithError(c, response.StatusInternalServerError, errorResp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse locale
|
||||||
|
locale := "en-us" // Default locale
|
||||||
|
if loc := c.Query("locale"); loc != "" {
|
||||||
|
locale = strings.ToLower(strings.TrimSpace(loc))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse filter parameters
|
||||||
|
typeParam := strings.TrimSpace(c.Query("type"))
|
||||||
|
if typeParam == "" {
|
||||||
|
typeParam = "assistant" // Default type
|
||||||
|
}
|
||||||
|
connector := strings.TrimSpace(c.Query("connector"))
|
||||||
|
keywords := strings.TrimSpace(c.Query("keywords"))
|
||||||
|
|
||||||
|
// Parse boolean filters
|
||||||
|
var builtIn, mentionable, automated *bool
|
||||||
|
if builtInParam := c.Query("built_in"); builtInParam != "" {
|
||||||
|
builtIn = parseBoolValue(builtInParam)
|
||||||
|
}
|
||||||
|
if mentionableParam := c.Query("mentionable"); mentionableParam != "" {
|
||||||
|
mentionable = parseBoolValue(mentionableParam)
|
||||||
|
}
|
||||||
|
if automatedParam := c.Query("automated"); automatedParam != "" {
|
||||||
|
automated = parseBoolValue(automatedParam)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build filter
|
||||||
|
filter := BuildAssistantFilter(AssistantFilterParams{
|
||||||
|
Type: typeParam,
|
||||||
|
Connector: connector,
|
||||||
|
Keywords: keywords,
|
||||||
|
BuiltIn: builtIn,
|
||||||
|
Mentionable: mentionable,
|
||||||
|
Automated: automated,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Apply permission-based filtering (Scope filtering)
|
||||||
|
filter.QueryFilter = AuthQueryFilter(c, authInfo)
|
||||||
|
|
||||||
|
// Get tags with filter
|
||||||
|
tags, err := agentInstance.Store.GetAssistantTags(filter, locale)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to get assistant tags: %v", err)
|
||||||
|
errorResp := &response.ErrorResponse{
|
||||||
|
Code: response.ErrServerError.Code,
|
||||||
|
ErrorDescription: "Failed to get assistant tags: " + err.Error(),
|
||||||
|
}
|
||||||
|
response.RespondWithError(c, response.StatusInternalServerError, errorResp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the result with standard response format
|
||||||
|
response.RespondWithSuccess(c, response.StatusOK, map[string]interface{}{
|
||||||
|
"data": tags,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -720,6 +720,206 @@ func TestAssistantEdgeCases(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestListAssistantTags tests the assistant tags endpoint
|
||||||
|
func TestListAssistantTags(t *testing.T) {
|
||||||
|
serverURL := testutils.Prepare(t)
|
||||||
|
defer testutils.Clean()
|
||||||
|
|
||||||
|
baseURL := ""
|
||||||
|
if openapi.Server != nil && openapi.Server.Config != nil {
|
||||||
|
baseURL = openapi.Server.Config.BaseURL
|
||||||
|
}
|
||||||
|
|
||||||
|
client := testutils.RegisterTestClient(t, "Agent Tags Test Client", []string{"https://localhost/callback"})
|
||||||
|
defer testutils.CleanupTestClient(t, client.ClientID)
|
||||||
|
tokenInfo := testutils.ObtainAccessToken(t, serverURL, client.ClientID, client.ClientSecret, "https://localhost/callback", "openid profile")
|
||||||
|
|
||||||
|
t.Run("ListAssistantTagsSuccess", func(t *testing.T) {
|
||||||
|
// Test listing all assistant tags
|
||||||
|
req, err := http.NewRequest("GET", serverURL+baseURL+"/agent/assistants/tags", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, resp)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode, "Should successfully retrieve tags")
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data, hasData := response["data"].([]interface{})
|
||||||
|
if hasData {
|
||||||
|
t.Logf("Successfully retrieved %d tags", len(data))
|
||||||
|
|
||||||
|
// Verify tag structure
|
||||||
|
if len(data) > 0 {
|
||||||
|
tag, ok := data[0].(map[string]interface{})
|
||||||
|
if ok {
|
||||||
|
assert.Contains(t, tag, "value", "Tag should have value field")
|
||||||
|
assert.Contains(t, tag, "label", "Tag should have label field")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAssistantTagsWithLocale", func(t *testing.T) {
|
||||||
|
// Test with locale parameter
|
||||||
|
req, err := http.NewRequest("GET", serverURL+baseURL+"/agent/assistants/tags?locale=zh-cn", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, resp)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data, hasData := response["data"].([]interface{})
|
||||||
|
if hasData {
|
||||||
|
t.Logf("Successfully retrieved %d tags with zh-cn locale", len(data))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAssistantTagsWithFilters", func(t *testing.T) {
|
||||||
|
// Test with type filter
|
||||||
|
req, err := http.NewRequest("GET", serverURL+baseURL+"/agent/assistants/tags?type=assistant", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, resp)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data, hasData := response["data"].([]interface{})
|
||||||
|
if hasData {
|
||||||
|
t.Logf("Successfully retrieved %d tags with type filter", len(data))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAssistantTagsWithConnector", func(t *testing.T) {
|
||||||
|
// Test with connector filter
|
||||||
|
req, err := http.NewRequest("GET", serverURL+baseURL+"/agent/assistants/tags?connector=openai", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, resp)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data, hasData := response["data"].([]interface{})
|
||||||
|
if hasData {
|
||||||
|
t.Logf("Successfully retrieved %d tags for openai connector", len(data))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAssistantTagsWithBuiltInFilter", func(t *testing.T) {
|
||||||
|
// Test with built_in filter
|
||||||
|
req, err := http.NewRequest("GET", serverURL+baseURL+"/agent/assistants/tags?built_in=false", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, resp)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data, hasData := response["data"].([]interface{})
|
||||||
|
if hasData {
|
||||||
|
t.Logf("Successfully retrieved %d tags for non-built-in assistants", len(data))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAssistantTagsWithMentionableFilter", func(t *testing.T) {
|
||||||
|
// Test with mentionable filter
|
||||||
|
req, err := http.NewRequest("GET", serverURL+baseURL+"/agent/assistants/tags?mentionable=true", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, resp)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data, hasData := response["data"].([]interface{})
|
||||||
|
if hasData {
|
||||||
|
t.Logf("Successfully retrieved %d tags for mentionable assistants", len(data))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAssistantTagsWithKeywords", func(t *testing.T) {
|
||||||
|
// Test with keywords filter
|
||||||
|
req, err := http.NewRequest("GET", serverURL+baseURL+"/agent/assistants/tags?keywords=test", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, resp)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data, hasData := response["data"].([]interface{})
|
||||||
|
if hasData {
|
||||||
|
t.Logf("Successfully retrieved %d tags with keywords filter", len(data))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAssistantTagsUnauthorized", func(t *testing.T) {
|
||||||
|
// Test without authentication
|
||||||
|
req, err := http.NewRequest("GET", serverURL+baseURL+"/agent/assistants/tags", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// No Authorization header
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, resp)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
||||||
|
t.Logf("Correctly rejected unauthorized request")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// BenchmarkListAssistants benchmarks the list assistants endpoint
|
// BenchmarkListAssistants benchmarks the list assistants endpoint
|
||||||
func BenchmarkListAssistants(b *testing.B) {
|
func BenchmarkListAssistants(b *testing.B) {
|
||||||
// Convert testing.B to testing.T for Prepare/Clean
|
// Convert testing.B to testing.T for Prepare/Clean
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue