feat(plugin): search & category list

This commit is contained in:
lijunwen.gigoo
2025-10-10 17:45:52 +08:00
parent a363dbef2b
commit eb7028391b
6 changed files with 87 additions and 73 deletions

View File

@ -331,7 +331,7 @@ func PublicGetProductCategoryList(ctx context.Context, c *app.RequestContext) {
}
var resp *product_public_api.GetProductCategoryListResponse
req.EntityType = product_common.ProductEntityType_SaasPlugin
switch req.GetEntityType() {
case product_common.ProductEntityType_SaasPlugin:
resp, err = plugin.PluginApplicationSVC.GetSaasProductCategoryList(ctx, &req)

View File

@ -1,19 +1,3 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Code generated by thriftgo (0.4.2). DO NOT EDIT.
package product_public_api
@ -1477,9 +1461,9 @@ func (p *SearchProductRequest) String() string {
}
type SearchProductResponse struct {
Code int32 `thrift:"Code,1,required" form:"Code,required" json:"Code,required" query:"Code,required"`
Message string `thrift:"Message,2,required" form:"Message,required" json:"Message,required" query:"Message,required"`
Data *SearchProductResponseData `thrift:"Data,3,optional" form:"Data" json:"Data,omitempty" query:"Data"`
Code int32 `thrift:"Code,1,required" form:"code,required" json:"code,required"`
Message string `thrift:"Message,2,required" form:"message,required" json:"message,required"`
Data *SearchProductResponseData `thrift:"Data,3,optional" form:"data" json:"data,omitempty"`
BaseResp *base.BaseResp `thrift:"BaseResp,255,optional" form:"BaseResp" json:"BaseResp,omitempty" query:"BaseResp"`
}
@ -1782,11 +1766,11 @@ func (p *SearchProductResponse) String() string {
}
type SearchProductResponseData struct {
Products []*ProductInfo `thrift:"Products,1,optional" form:"Products" json:"Products,omitempty" query:"Products"`
Total *int32 `thrift:"Total,2,optional" form:"Total" json:"Total,omitempty" query:"Total"`
HasMore *bool `thrift:"HasMore,3,optional" form:"HasMore" json:"HasMore,omitempty" query:"HasMore"`
Products []*ProductInfo `thrift:"Products,1,optional" form:"products" json:"products,omitempty"`
Total *int32 `thrift:"Total,2,optional" form:"total" json:"total,omitempty"`
HasMore *bool `thrift:"HasMore,3,optional" form:"has_more" json:"has_more,omitempty"`
// Entity count
EntityTotal map[product_common.ProductEntityType]int32 `thrift:"EntityTotal,4,optional" form:"EntityTotal" json:"EntityTotal,omitempty" query:"EntityTotal"`
EntityTotal map[product_common.ProductEntityType]int32 `thrift:"EntityTotal,4,optional" form:"entity_total" json:"entity_total,omitempty"`
}
func NewSearchProductResponseData() *SearchProductResponseData {
@ -2150,9 +2134,9 @@ func (p *SearchProductResponseData) String() string {
}
type SearchSuggestResponse struct {
Code int32 `thrift:"Code,1,required" form:"Code,required" json:"Code,required" query:"Code,required"`
Message string `thrift:"Message,2,required" form:"Message,required" json:"Message,required" query:"Message,required"`
Data *SearchSuggestResponseData `thrift:"Data,3,optional" form:"Data" json:"Data,omitempty" query:"Data"`
Code int32 `thrift:"Code,1,required" form:"code,required" json:"code,required"`
Message string `thrift:"Message,2,required" form:"message,required" json:"message,required"`
Data *SearchSuggestResponseData `thrift:"Data,3,optional" form:"data" json:"data,omitempty"`
BaseResp *base.BaseResp `thrift:"BaseResp,255,optional" form:"BaseResp" json:"BaseResp,omitempty" query:"BaseResp"`
}
@ -2456,9 +2440,9 @@ func (p *SearchSuggestResponse) String() string {
type SearchSuggestResponseData struct {
// Deprecated
Suggestions []*ProductMetaInfo `thrift:"Suggestions,1,optional" form:"Suggestions" json:"Suggestions,omitempty" query:"Suggestions"`
HasMore *bool `thrift:"HasMore,2,optional" form:"HasMore" json:"HasMore,omitempty" query:"HasMore"`
SuggestionV2 []*ProductInfo `thrift:"SuggestionV2,3,optional" form:"SuggestionV2" json:"SuggestionV2,omitempty" query:"SuggestionV2"`
Suggestions []*ProductMetaInfo `thrift:"Suggestions,1,optional" form:"suggestions" json:"suggestions,omitempty"`
HasMore *bool `thrift:"HasMore,2,optional" form:"has_more" json:"has_more,omitempty"`
SuggestionV2 []*ProductInfo `thrift:"SuggestionV2,3,optional" form:"suggestion_v2" json:"suggestion_v2,omitempty"`
}
func NewSearchSuggestResponseData() *SearchSuggestResponseData {
@ -26784,8 +26768,8 @@ func (p *GetProductCategoryListRequest) String() string {
}
type GetProductCategoryListData struct {
EntityType product_common.ProductEntityType `thrift:"EntityType,1,required" form:"EntityType,required" json:"EntityType,required" query:"EntityType,required"`
Categories []*ProductCategory `thrift:"Categories,2,optional" form:"Categories" json:"Categories,omitempty" query:"Categories"`
EntityType product_common.ProductEntityType `thrift:"EntityType,1,required" form:"entity_type,required" json:"entity_type,required"`
Categories []*ProductCategory `thrift:"Categories,2,optional" form:"categories" json:"categories,omitempty"`
}
func NewGetProductCategoryListData() *GetProductCategoryListData {
@ -27007,9 +26991,9 @@ func (p *GetProductCategoryListData) String() string {
}
type GetProductCategoryListResponse struct {
Code int32 `thrift:"Code,1,required" form:"Code,required" json:"Code,required" query:"Code,required"`
Message string `thrift:"Message,2,required" form:"Message,required" json:"Message,required" query:"Message,required"`
Data *GetProductCategoryListData `thrift:"Data,3" form:"Data" json:"Data" query:"Data"`
Code int32 `thrift:"Code,1,required" form:"code,required" json:"code,required"`
Message string `thrift:"Message,2,required" form:"message,required" json:"message,required"`
Data *GetProductCategoryListData `thrift:"Data,3" form:"data" json:"data"`
BaseResp *base.BaseResp `thrift:"BaseResp,255,optional" form:"BaseResp" json:"BaseResp,omitempty" query:"BaseResp"`
}

View File

@ -326,6 +326,12 @@ func convertPluginToProductInfo(plugin *entity.PluginInfo) *productAPI.ProductIn
Description: plugin.GetDesc(),
IconURL: plugin.GetIconURI(),
ListedAt: plugin.CreatedAt,
EntityType: productCommon.ProductEntityType_Plugin,
IsOfficial: true,
Status: productCommon.ProductStatus_Listed,
UserInfo: &productCommon.UserInfo{
Name: "Coze Official",
},
},
}
}
@ -348,6 +354,21 @@ func (p *PluginApplicationService) convertPluginsToProductInfos(ctx context.Cont
}
return products
}
func (p *PluginApplicationService) convertPluginsToMetaInfos(ctx context.Context, plugins []*entity.PluginInfo, tools map[int64][]*entity.ToolInfo) []*productAPI.ProductMetaInfo {
products := make([]*productAPI.ProductMetaInfo, 0, len(plugins))
for _, plugin := range plugins {
pi := &productAPI.ProductMetaInfo{
ID: plugin.ID,
Name: plugin.GetName(),
Description: plugin.GetDesc(),
IconURL: plugin.GetIconURI(),
ListedAt: plugin.CreatedAt,
EntityID: plugin.ID,
}
products = append(products, pi)
}
return products
}
func (p *PluginApplicationService) getSaasPluginList(ctx context.Context, domainReq *dto.ListSaasPluginProductsRequest) (*dto.ListPluginProductsResponse, error) {
return p.DomainSVC.ListSaasPluginProducts(ctx, domainReq)
@ -402,10 +423,15 @@ func (p *PluginApplicationService) GetCozeSaasPluginList(ctx context.Context, re
func (p *PluginApplicationService) PublicSearchProduct(ctx context.Context, req *productAPI.SearchProductRequest) (resp *productAPI.SearchProductResponse, err error) {
domainResp, err := p.getSaasPluginList(ctx, &dto.ListSaasPluginProductsRequest{
PageNum: ptr.Of(req.PageNum),
PageSize: ptr.Of(req.PageSize),
Keyword: ptr.Of(req.Keyword),
EntityTypes: p.convertEntityTypesStrToSlice(*req.EntityTypes),
PageNum: ptr.Of(req.PageNum),
PageSize: ptr.Of(req.PageSize),
Keyword: ptr.Of(req.Keyword),
EntityTypes: func() []productCommon.ProductEntityType {
if req.EntityTypes == nil {
return nil
}
return p.convertEntityTypesStrToSlice(*req.EntityTypes)
}(),
CategoryIDs: req.CategoryIDs,
IsOfficial: req.IsOfficial,
PluginType: req.PluginType,
@ -462,11 +488,17 @@ func (p *PluginApplicationService) convertEntityTypesStrToSlice(entityTypesStr s
}
func (p *PluginApplicationService) PublicSearchSuggest(ctx context.Context, req *productAPI.SearchSuggestRequest) (resp *productAPI.SearchSuggestResponse, err error) {
domainResp, err := p.getSaasPluginList(ctx, &dto.ListSaasPluginProductsRequest{
PageNum: req.PageNum,
PageSize: req.PageSize,
Keyword: req.Keyword,
EntityTypes: p.convertEntityTypesStrToSlice(*req.EntityTypes),
PageNum: req.PageNum,
PageSize: req.PageSize,
Keyword: req.Keyword,
EntityTypes: func() []productCommon.ProductEntityType {
if req.EntityTypes == nil {
return nil
}
return p.convertEntityTypesStrToSlice(*req.EntityTypes)
}(),
})
if err != nil {
logs.CtxErrorf(ctx, "ListSaasPluginProducts for suggestions failed: %v", err)
return &productAPI.SearchSuggestResponse{
@ -497,6 +529,7 @@ func (p *PluginApplicationService) PublicSearchSuggest(ctx context.Context, req
Message: "success",
Data: &productAPI.SearchSuggestResponseData{
SuggestionV2: suggestionProducts,
Suggestions: p.convertPluginsToMetaInfos(ctx, domainResp.Plugins, tools),
HasMore: ptr.Of(domainResp.HasMore),
},
}, nil

View File

@ -232,26 +232,23 @@ type JsonSchema struct {
Extra map[string]*JsonSchema `json:"-"`
}
type SaasPluginToolsListResponse struct {
Items []SaasPluginToolsList `json:"items"`
}
type SaasPluginToolsList struct {
Tools []Tools `json:"tools"`
PluginID string `json:"plugin_id"`
McpJSON string `json:"mcp_json"`
Tools []Tools `json:"tools"`
PluginID string `json:"plugin_id"`
McpJSON string `json:"mcp_json"`
}
type Tools struct {
ToolID string `json:"tool_id"`
Description string `json:"description"`
InputSchema *JsonSchema `json:"inputSchema"`
Name string `json:"name"`
OutputSchema *JsonSchema `json:"outputSchema"`
ToolID string `json:"tool_id"`
Description string `json:"description"`
InputSchema *JsonSchema `json:"inputSchema"`
Name string `json:"name"`
OutputSchema *JsonSchema `json:"outputSchema"`
}
// stringToJsonSchemaType converts a string to JsonSchemaType
func stringToJsonSchemaType(s string) JsonSchemaType {
switch s {

View File

@ -446,4 +446,4 @@ func TestBatchGetSaasPluginToolsInfoIntegration(t *testing.T) {
assert.Equal(t, pluginCommon.ParameterType_Bool, imageParam.Type)
assert.Equal(t, pluginCommon.ParameterLocation_Body, imageParam.Location)
assert.Equal(t, "是否需要返回图片url", imageParam.Desc)
}
}

View File

@ -45,30 +45,30 @@ struct SearchProductRequest{
}
struct SearchProductResponse{
1 : required i32 Code (agw.key = "code") ,
2 : required string Message (agw.key = "message"),
3 : optional SearchProductResponseData Data (agw.key = "data") ,
1 : required i32 Code (agw.key = "code",api.body = "code") ,
2 : required string Message (agw.key = "message",api.body = "message"),
3 : optional SearchProductResponseData Data (agw.key = "data",api.body = "data") ,
255: optional base.BaseResp BaseResp ,
}
struct SearchProductResponseData{
1: optional list<ProductInfo> Products (agw.key = "products"),
2: optional i32 Total (agw.key = "total") ,
3: optional bool HasMore (agw.key = "has_more"),
4: optional map<product_common.ProductEntityType, i32> EntityTotal (agw.key = "entity_total"), // Entity count
1: optional list<ProductInfo> Products (agw.key = "products",api.body = "products"),
2: optional i32 Total (agw.key = "total",api.body = "total") ,
3: optional bool HasMore (agw.key = "has_more",api.body = "has_more"),
4: optional map<product_common.ProductEntityType, i32> EntityTotal (agw.key = "entity_total",api.body = "entity_total"), // Entity count
}
struct SearchSuggestResponse{
1 : required i32 Code (agw.key = "code") ,
2 : required string Message (agw.key = "message"),
3 : optional SearchSuggestResponseData Data (agw.key = "data") ,
1 : required i32 Code (agw.key = "code",api.body = "code") ,
2 : required string Message (agw.key = "message",api.body = "message"),
3 : optional SearchSuggestResponseData Data (agw.key = "data",api.body = "data") ,
255: optional base.BaseResp BaseResp ,
}
struct SearchSuggestResponseData{
1: optional list<ProductMetaInfo> Suggestions (agw.key = "suggestions"), // Deprecated
2: optional bool HasMore (agw.key = "has_more"),
3: optional list<ProductInfo> SuggestionV2(agw.key = "suggestion_v2"),
1: optional list<ProductMetaInfo> Suggestions (agw.key = "suggestions",api.body = "suggestions"), // Deprecated
2: optional bool HasMore (agw.key = "has_more",api.body = "has_more"),
3: optional list<ProductInfo> SuggestionV2(agw.key = "suggestion_v2",api.body = "suggestion_v2"),
}
@ -648,14 +648,14 @@ struct GetProductCategoryListRequest {
}
struct GetProductCategoryListData{
1: required product_common.ProductEntityType EntityType (agw.key = "entity_type"),
2: optional list<ProductCategory> Categories (agw.key = "categories") ,
1: required product_common.ProductEntityType EntityType (agw.key = "entity_type", api.body= "entity_type"),
2: optional list<ProductCategory> Categories (agw.key = "categories", api.body= "categories") ,
}
struct GetProductCategoryListResponse {
1 : required i32 Code (agw.key = "code") ,
2 : required string Message (agw.key = "message"),
3 : GetProductCategoryListData Data (agw.key = "data") ,
1 : required i32 Code (agw.key = "code", api.body= "code") ,
2 : required string Message (agw.key = "message", api.body= "message"),
3 : GetProductCategoryListData Data (agw.key = "data", api.body= "data") ,
255: optional base.BaseResp BaseResp ,
}