feat(plugin): tool list

This commit is contained in:
lijunwen.gigoo
2025-10-10 10:31:25 +08:00
parent ea38e101d2
commit 5bc8302dd3
27 changed files with 1029 additions and 105 deletions

View File

@ -40,6 +40,7 @@ import (
"github.com/coze-dev/coze-studio/backend/application/search"
"github.com/coze-dev/coze-studio/backend/application/singleagent"
"github.com/coze-dev/coze-studio/backend/application/template"
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
"github.com/coze-dev/coze-studio/backend/pkg/logs"
)
@ -54,6 +55,7 @@ func PublicGetProductList(ctx context.Context, c *app.RequestContext) {
return
}
req.EntityType = ptr.Of(product_common.ProductEntityType_SaasPlugin)
var resp *product_public_api.GetProductListResponse
switch req.GetEntityType() {
case product_common.ProductEntityType_Plugin:

View File

@ -327,54 +327,58 @@ func convertPluginToProductInfo(plugin *entity.PluginInfo) *productAPI.ProductIn
IconURL: plugin.GetIconURI(),
ListedAt: plugin.CreatedAt,
},
PluginExtra: &productAPI.PluginExtraInfo{
IsOfficial: plugin.IsOfficial(),
},
}
}
// convertPluginsToProductInfos converts a slice of plugins to ProductInfo slice
func convertPluginsToProductInfos(plugins []*entity.PluginInfo) []*productAPI.ProductInfo {
func (p *PluginApplicationService) convertPluginsToProductInfos(ctx context.Context, plugins []*entity.PluginInfo, tools map[int64][]*entity.ToolInfo) []*productAPI.ProductInfo {
products := make([]*productAPI.ProductInfo, 0, len(plugins))
for _, plugin := range plugins {
products = append(products, convertPluginToProductInfo(plugin))
var pExtra *productAPI.PluginExtraInfo
if tool, exist := tools[plugin.ID]; exist {
pluginExtra, err := p.buildPluginProductExtraInfo(ctx, plugin, tool)
if err != nil {
logs.CtxErrorf(ctx, "buildPluginProductExtraInfo failed: %v", err)
} else {
pExtra = pluginExtra
}
}
pi := convertPluginToProductInfo(plugin)
pi.PluginExtra = pExtra
products = append(products, pi)
}
return products
}
// getSaasPluginList is a common method to get SaaS plugin list from domain service
func (t *PluginApplicationService) getSaasPluginList(ctx context.Context) ([]*entity.PluginInfo, int64, error) {
domainReq := &dto.ListPluginProductsRequest{}
domainResp, err := t.DomainSVC.ListSaasPluginProducts(ctx, domainReq)
if err != nil {
return nil, 0, err
}
return domainResp.Plugins, domainResp.Total, nil
func (p *PluginApplicationService) getSaasPluginList(ctx context.Context, domainReq *dto.ListSaasPluginProductsRequest) (*dto.ListPluginProductsResponse, error) {
return p.DomainSVC.ListSaasPluginProducts(ctx, domainReq)
}
// convertPluginsToSuggestions converts plugins to suggestion products with deduplication and limit
func convertPluginsToSuggestions(plugins []*entity.PluginInfo, limit int) []*productAPI.ProductInfo {
func (p *PluginApplicationService) getSaasPluginToolsList(ctx context.Context, pluginIDs []int64) (map[int64][]*entity.ToolInfo, error) {
return p.DomainSVC.BatchGetSaasPluginToolsInfo(ctx, pluginIDs)
}
func convertPluginsToSuggestions(plugins []*entity.PluginInfo) []*productAPI.ProductInfo {
suggestionProducts := make([]*productAPI.ProductInfo, 0, len(plugins))
suggestionSet := make(map[string]bool) // Use map to avoid duplicates
for _, plugin := range plugins {
// Add plugin as suggestion if name is unique
if plugin.GetName() != "" && !suggestionSet[plugin.GetName()] {
suggestionProducts = append(suggestionProducts, convertPluginToProductInfo(plugin))
suggestionSet[plugin.GetName()] = true
}
// Limit suggestions to avoid too many results
if len(suggestionProducts) >= limit {
break
}
}
return suggestionProducts
}
func (t *PluginApplicationService) GetCozeSaasPluginList(ctx context.Context, req *productAPI.GetProductListRequest) (resp *productAPI.GetProductListResponse, err error) {
plugins, total, err := t.getSaasPluginList(ctx)
func (p *PluginApplicationService) GetCozeSaasPluginList(ctx context.Context, req *productAPI.GetProductListRequest) (resp *productAPI.GetProductListResponse, err error) {
domainResp, err := p.getSaasPluginList(ctx, &dto.ListSaasPluginProductsRequest{
PageNum: ptr.Of(req.PageNum),
PageSize: ptr.Of(req.PageSize),
Keyword: req.Keyword,
EntityTypes: req.EntityTypes,
})
if err != nil {
logs.CtxErrorf(ctx, "ListSaasPluginProducts failed: %v", err)
return &productAPI.GetProductListResponse{
@ -383,21 +387,44 @@ func (t *PluginApplicationService) GetCozeSaasPluginList(ctx context.Context, re
}, nil
}
products := convertPluginsToProductInfos(plugins)
// tools
pluginIDs := make([]int64, 0, len(domainResp.Plugins))
for _,product := range domainResp.Plugins{
pluginIDs = append(pluginIDs, product.ID)
}
tools, err := p.getSaasPluginToolsList(ctx, pluginIDs)
if err != nil {
logs.CtxErrorf(ctx, "BatchGetSaasPluginToolsInfo failed: %v", err)
return &productAPI.GetProductListResponse{
Code: -1,
Message: "Failed to get SaaS plugin tools list",
}, nil
}
products := p.convertPluginsToProductInfos(ctx, domainResp.Plugins, tools)
return &productAPI.GetProductListResponse{
Code: 0,
Message: "success",
Data: &productAPI.GetProductListData{
Products: products,
Total: int32(total),
HasMore: false,
Total: int32(domainResp.Total),
HasMore: domainResp.HasMore,
},
}, nil
}
func (t *PluginApplicationService) PublicSearchProduct(ctx context.Context, req *productAPI.SearchProductRequest) (resp *productAPI.SearchProductResponse, err error) {
plugins, total, err := t.getSaasPluginList(ctx)
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: req.EntityTypes,
CategoryIDs: req.CategoryIDs,
IsOfficial: req.IsOfficial,
PluginType: req.PluginType,
})
if err != nil {
logs.CtxErrorf(ctx, "ListSaasPluginProducts failed: %v", err)
return &productAPI.SearchProductResponse{
@ -405,22 +432,42 @@ func (t *PluginApplicationService) PublicSearchProduct(ctx context.Context, req
Message: "Failed to search SaaS plugins",
}, nil
}
// tools
pluginIDs := make([]int64, 0, len(domainResp.Plugins))
for _,product := range domainResp.Plugins{
pluginIDs = append(pluginIDs, product.ID)
}
products := convertPluginsToProductInfos(plugins)
tools, err := p.getSaasPluginToolsList(ctx, pluginIDs)
if err != nil {
logs.CtxErrorf(ctx, "BatchGetSaasPluginToolsInfo failed: %v", err)
return &productAPI.SearchProductResponse{
Code: -1,
Message: "Failed to get SaaS plugin tools list",
}, nil
}
products := p.convertPluginsToProductInfos(ctx, domainResp.Plugins, tools)
return &productAPI.SearchProductResponse{
Code: 0,
Message: "success",
Data: &productAPI.SearchProductResponseData{
Products: products,
Total: ptr.Of(int32(total)),
HasMore: ptr.Of(false),
Total: ptr.Of(int32(domainResp.Total)),
HasMore: ptr.Of(domainResp.HasMore),
},
}, nil
}
func (t *PluginApplicationService) PublicSearchSuggest(ctx context.Context, req *productAPI.SearchSuggestRequest) (resp *productAPI.SearchSuggestResponse, err error) {
plugins, _, err := t.getSaasPluginList(ctx)
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: req.EntityTypes,
})
if err != nil {
logs.CtxErrorf(ctx, "ListSaasPluginProducts for suggestions failed: %v", err)
return &productAPI.SearchSuggestResponse{
@ -429,30 +476,27 @@ func (t *PluginApplicationService) PublicSearchSuggest(ctx context.Context, req
}, nil
}
// Convert plugins to suggestions with limit of 10
suggestionProducts := convertPluginsToSuggestions(plugins, 10)
suggestionProducts := convertPluginsToSuggestions(domainResp.Plugins)
return &productAPI.SearchSuggestResponse{
Code: 0,
Message: "success",
Data: &productAPI.SearchSuggestResponseData{
SuggestionV2: suggestionProducts,
HasMore: ptr.Of(false),
HasMore: ptr.Of(domainResp.HasMore),
},
}, nil
}
func (t *PluginApplicationService) GetSaasProductCategoryList(ctx context.Context, req *productAPI.GetProductCategoryListRequest) (resp *productAPI.GetProductCategoryListResponse, err error) {
// 构建 domain 层请求
func (p *PluginApplicationService) GetSaasProductCategoryList(ctx context.Context, req *productAPI.GetProductCategoryListRequest) (resp *productAPI.GetProductCategoryListResponse, err error) {
domainReq := &dto.ListPluginCategoriesRequest{}
// 根据请求参数设置查询条件
if req.GetEntityType() == productCommon.ProductEntityType_SaasPlugin {
domainReq.EntityType = ptr.Of("plugin")
}
// 调用 domain 层服务
domainResp, err := t.DomainSVC.ListSaasPluginCategories(ctx, domainReq)
domainResp, err := p.DomainSVC.ListSaasPluginCategories(ctx, domainReq)
if err != nil {
logs.CtxErrorf(ctx, "ListSaasPluginCategories failed: %v", err)
return &productAPI.GetProductCategoryListResponse{
@ -484,7 +528,7 @@ func (t *PluginApplicationService) GetSaasProductCategoryList(ctx context.Contex
}, nil
}
func (t *PluginApplicationService) GetProductCallInfo(ctx context.Context, req *productAPI.GetProductCallInfoRequest) (resp *productAPI.GetProductCallInfoResponse, err error) {
func (p *PluginApplicationService) GetProductCallInfo(ctx context.Context, req *productAPI.GetProductCallInfoRequest) (resp *productAPI.GetProductCallInfoResponse, err error) {
userID := ctxutil.GetUIDFromCtx(ctx)
if userID == nil {
return &productAPI.GetProductCallInfoResponse{
@ -493,8 +537,7 @@ func (t *PluginApplicationService) GetProductCallInfo(ctx context.Context, req *
}, nil
}
// Call GetSaasUserInfo
_, err = t.userSVC.GetSaasUserInfo(ctx)
_, err = p.userSVC.GetSaasUserInfo(ctx)
if err != nil {
logs.CtxErrorf(ctx, "GetSaasUserInfo failed: %v", err)
return &productAPI.GetProductCallInfoResponse{
@ -503,8 +546,7 @@ func (t *PluginApplicationService) GetProductCallInfo(ctx context.Context, req *
}, nil
}
// Call GetUserBenefit
benefit, err := t.userSVC.GetUserBenefit(ctx)
benefit, err := p.userSVC.GetUserBenefit(ctx)
if err != nil {
logs.CtxErrorf(ctx, "GetUserBenefit failed: %v", err)
return &productAPI.GetProductCallInfoResponse{

View File

@ -17,6 +17,7 @@
package model
import (
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
api "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop/common"
)
@ -44,6 +45,9 @@ type PluginInfo struct {
CreatedAt int64
UpdatedAt int64
Source *bot_common.PluginSource
Extra map[string]any
Manifest *PluginManifest
OpenapiDoc *Openapi3T
}

View File

@ -44,6 +44,9 @@ type ToolInfo struct {
ActivatedStatus *consts.ActivatedStatus
DebugStatus *common.APIDebugStatus
Source *bot_common.PluginSource
Extra map[string]any
Method *string
SubURL *string
Operation *Openapi3Operation

View File

@ -16,6 +16,10 @@
package dto
import (
"encoding/json"
)
// SearchSaasPluginRequest represents the request parameters for searching SaaS plugins
type SearchSaasPluginRequest struct {
Keyword *string `json:"keyword,omitempty"`
@ -26,6 +30,8 @@ type SearchSaasPluginRequest struct {
IsOfficial *bool `json:"is_official,omitempty"`
}
// SearchSaasPluginResponse represents the response from coze.cn search API
type SearchSaasPluginResponse struct {
Code int `json:"code"`
@ -129,3 +135,158 @@ type GetSaasPluginCallInfoResponse struct {
type GetSaasPluginCallInfoData struct {
}
type JsonSchemaType int32
const (
JsonSchemaType_STRING JsonSchemaType = 1
JsonSchemaType_NUMBER JsonSchemaType = 2
JsonSchemaType_INTEGER JsonSchemaType = 3
JsonSchemaType_BOOLEAN JsonSchemaType = 4
JsonSchemaType_OBJECT JsonSchemaType = 5
JsonSchemaType_ARRAY JsonSchemaType = 6
JsonSchemaType_NULL JsonSchemaType = 7
)
type AnyValue struct {
Type JsonSchemaType `json:"type,omitempty"`
StringValue string `json:"stringValue,omitempty"`
}
type JsonSchema struct {
// core
ID string `json:"$id,omitempty"`
Schema string `json:"$schema,omitempty"`
Ref string `json:"$ref,omitempty"`
Comment string `json:"$comment,omitempty"`
Defs map[string]*JsonSchema `json:"$defs,omitempty"`
Definitions map[string]*JsonSchema `json:"definitions,omitempty"` // deprecated but still allowed
Anchor string `json:"$anchor,omitempty"`
DynamicAnchor string `json:"$dynamicAnchor,omitempty"`
DynamicRef string `json:"$dynamicRef,omitempty"`
Vocabulary map[string]bool `json:"$vocabulary,omitempty"`
// metadata
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Default []byte `json:"default,omitempty"`
Deprecated bool `json:"deprecated,omitempty"`
ReadOnly bool `json:"readOnly,omitempty"`
WriteOnly bool `json:"writeOnly,omitempty"`
// validation
// Use Type for a single type, or Types for multiple types; never both.
Type JsonSchemaType `json:"type,omitempty"`
Types []JsonSchemaType `json:"types,omitempty"`
Enum []*AnyValue `json:"enum,omitempty"`
MultipleOf *float64 `json:"multipleOf,omitempty"`
Minimum *float64 `json:"minimum,omitempty"`
Maximum *float64 `json:"maximum,omitempty"`
ExclusiveMinimum *bool `json:"exclusiveMinimum,omitempty"`
ExclusiveMaximum *bool `json:"exclusiveMaximum,omitempty"`
MinLength *int32 `json:"minLength,omitempty"`
MaxLength *int32 `json:"maxLength,omitempty"`
Pattern string `json:"pattern,omitempty"`
// arrays
PrefixItems []*JsonSchema `json:"prefixItems,omitempty"`
Items *JsonSchema `json:"items,omitempty"`
MinItems *int32 `json:"minItems,omitempty"`
MaxItems *int32 `json:"maxItems,omitempty"`
AdditionalItems *JsonSchema `json:"additionalItems,omitempty"`
UniqueItems bool `json:"uniqueItems,omitempty"`
Contains *JsonSchema `json:"contains,omitempty"`
MinContains *int32 `json:"minContains,omitempty"`
MaxContains *int32 `json:"maxContains,omitempty"`
UnevaluatedItems *JsonSchema `json:"unevaluatedItems,omitempty"`
// objects
MinProperties *int32 `json:"minProperties,omitempty"`
MaxProperties *int32 `json:"maxProperties,omitempty"`
Required []string `json:"required,omitempty"`
DependentRequired map[string][]string `json:"dependentRequired,omitempty"`
Properties map[string]*JsonSchema `json:"properties,omitempty"`
PatternProperties map[string]*JsonSchema `json:"patternProperties,omitempty"`
AdditionalProperties *JsonSchema `json:"additionalProperties,omitempty"`
PropertyNames *JsonSchema `json:"propertyNames,omitempty"`
UnevaluatedProperties *JsonSchema `json:"unevaluatedProperties,omitempty"`
// logic
AllOf []*JsonSchema `json:"allOf,omitempty"`
AnyOf []*JsonSchema `json:"anyOf,omitempty"`
OneOf []*JsonSchema `json:"oneOf,omitempty"`
Not *JsonSchema `json:"not,omitempty"`
// conditional
If map[string]*JsonSchema `json:"if,omitempty"`
Then map[string]*JsonSchema `json:"then,omitempty"`
Else map[string]*JsonSchema `json:"else,omitempty"`
DependentSchemas map[string]*JsonSchema `json:"dependentSchemas,omitempty"`
// other
ContentEncoding *JsonSchema `json:"contentEncoding,omitempty"`
ContentMediaType *JsonSchema `json:"contentMediaType,omitempty"`
ContentSchema *JsonSchema `json:"contentSchema,omitempty"`
Format string `json:"format,omitempty"`
// Extra allows for additional keywords beyond those specified.
Extra map[string]*JsonSchema `json:"-"`
}
// stringToJsonSchemaType converts a string to JsonSchemaType
func stringToJsonSchemaType(s string) JsonSchemaType {
switch s {
case "string":
return JsonSchemaType_STRING
case "number":
return JsonSchemaType_NUMBER
case "integer":
return JsonSchemaType_INTEGER
case "boolean":
return JsonSchemaType_BOOLEAN
case "object":
return JsonSchemaType_OBJECT
case "array":
return JsonSchemaType_ARRAY
case "null":
return JsonSchemaType_NULL
default:
return JsonSchemaType_STRING // default fallback
}
}
// UnmarshalJSON implements custom JSON unmarshaling for JsonSchema
func (js *JsonSchema) UnmarshalJSON(data []byte) error {
// Create a temporary struct with the same fields but string type for Type field
type Alias JsonSchema
aux := &struct {
TypeString interface{} `json:"type"`
*Alias
}{
Alias: (*Alias)(js),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
// Handle the type field conversion
if aux.TypeString != nil {
switch v := aux.TypeString.(type) {
case string:
js.Type = stringToJsonSchemaType(v)
case []interface{}:
// Handle array of types
js.Types = make([]JsonSchemaType, len(v))
for i, typeVal := range v {
if typeStr, ok := typeVal.(string); ok {
js.Types[i] = stringToJsonSchemaType(typeStr)
}
}
}
}
return nil
}

View File

@ -17,6 +17,7 @@
package dto
import (
"github.com/coze-dev/coze-studio/backend/api/model/marketplace/product_common"
"github.com/coze-dev/coze-studio/backend/api/model/plugin_develop/common"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/consts"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/model"
@ -94,11 +95,23 @@ type CreateDraftPluginWithCodeResponse struct {
Tools []*entity.ToolInfo
}
type ListPluginProductsRequest struct{}
type ListPluginProductsRequest struct {
}
type ListSaasPluginProductsRequest struct {
PageNum *int32 `json:"page_num,omitempty"`
PageSize *int32 `json:"page_size,omitempty"`
Keyword *string `json:"keyword,omitempty"`
EntityTypes []product_common.ProductEntityType `json:"entity_types,omitempty"`
CategoryIDs []int64 `json:"category_ids,omitempty"`
IsOfficial *bool `json:"is_official,omitempty"`
PluginType *product_common.PluginType `json:"plugin_type,omitempty"`
}
type ListPluginProductsResponse struct {
Plugins []*entity.PluginInfo
Total int64
HasMore bool
}
type CopyPluginRequest struct {
@ -113,3 +126,51 @@ type CopyPluginResponse struct {
Plugin *entity.PluginInfo
Tools map[int64]*entity.ToolInfo // old tool id -> new tool
}
// DefaultParamSource 表示默认参数的设置来源
type DefaultParamSource int32
const (
DefaultParamSource_Input DefaultParamSource = 0 // 默认用户输入
DefaultParamSource_Variable DefaultParamSource = 1 // 引用变量
)
// AssistParameterType 表示辅助参数类型
type AssistParameterType int32
const (
AssistParameterType_DEFAULT AssistParameterType = 1
AssistParameterType_IMAGE AssistParameterType = 2
AssistParameterType_DOC AssistParameterType = 3
AssistParameterType_CODE AssistParameterType = 4
AssistParameterType_PPT AssistParameterType = 5
AssistParameterType_TXT AssistParameterType = 6
AssistParameterType_EXCEL AssistParameterType = 7
AssistParameterType_AUDIO AssistParameterType = 8
AssistParameterType_ZIP AssistParameterType = 9
AssistParameterType_VIDEO AssistParameterType = 10
)
type Parameter struct {
Name string `json:"name,omitempty"`
Desc string `json:"desc,omitempty"`
Required bool `json:"required,omitempty"`
Type string `json:"type,omitempty"`
SubParameters []*Parameter `json:"subParameters,omitempty"`
SubType string `json:"subType,omitempty"` // 如果Type是数组则有subtype
FromNodeId *string `json:"fromNodeId,omitempty"` // 如果入参的值是引用的则有fromNodeId
FromOutput []string `json:"fromOutput,omitempty"` // 具体引用哪个节点的key
Value *string `json:"value,omitempty"` // 如果入参是用户手输 就放这里
Format *string `json:"format,omitempty"`
Title *string `json:"title,omitempty"`
EnumList []string `json:"enumList,omitempty"`
EnumVarNames []string `json:"enumVarNames,omitempty"`
Minimum *float64 `json:"minimum,omitempty"`
Maximum *float64 `json:"maximum,omitempty"`
ExclusiveMinimum *bool `json:"exclusiveMinimum,omitempty"`
ExclusiveMaximum *bool `json:"exclusiveMaximum,omitempty"`
BizExtend *string `json:"bizExtend,omitempty"`
DefaultParamSource *DefaultParamSource `json:"defaultParamSource,omitempty"` // 默认入参的设置来源
VariableRef *string `json:"variableRef,omitempty"` // 引用variable的key
AssistType *AssistParameterType `json:"assistType,omitempty"`
}

View File

@ -1,3 +1,19 @@
/*
* 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 gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
@ -10,19 +26,21 @@ const TableNamePlugin = "plugin"
// Plugin Latest Plugin
type Plugin struct {
ID int64 `gorm:"column:id;primaryKey;comment:Plugin ID" json:"id"` // Plugin ID
SpaceID int64 `gorm:"column:space_id;not null;comment:Space ID" json:"space_id"` // Space ID
DeveloperID int64 `gorm:"column:developer_id;not null;comment:Developer ID" json:"developer_id"` // Developer ID
AppID int64 `gorm:"column:app_id;not null;comment:Application ID" json:"app_id"` // Application ID
IconURI string `gorm:"column:icon_uri;not null;comment:Icon URI" json:"icon_uri"` // Icon URI
ServerURL string `gorm:"column:server_url;not null;comment:Server URL" json:"server_url"` // Server URL
PluginType int32 `gorm:"column:plugin_type;not null;comment:Plugin Type, 1:http, 6:local" json:"plugin_type"` // Plugin Type, 1:http, 6:local
CreatedAt int64 `gorm:"column:created_at;not null;autoCreateTime:milli;comment:Create Time in Milliseconds" json:"created_at"` // Create Time in Milliseconds
UpdatedAt int64 `gorm:"column:updated_at;not null;autoUpdateTime:milli;comment:Update Time in Milliseconds" json:"updated_at"` // Update Time in Milliseconds
Version string `gorm:"column:version;not null;comment:Plugin Version, e.g. v1.0.0" json:"version"` // Plugin Version, e.g. v1.0.0
VersionDesc string `gorm:"column:version_desc;comment:Plugin Version Description" json:"version_desc"` // Plugin Version Description
Manifest *model.PluginManifest `gorm:"column:manifest;comment:Plugin Manifest;serializer:json" json:"manifest"` // Plugin Manifest
OpenapiDoc *model.Openapi3T `gorm:"column:openapi_doc;comment:OpenAPI Document, only stores the root;serializer:json" json:"openapi_doc"` // OpenAPI Document, only stores the root
ID int64 `gorm:"column:id;primaryKey;comment:Plugin ID" json:"id"` // Plugin ID
SpaceID int64 `gorm:"column:space_id;not null;comment:Space ID" json:"space_id"` // Space ID
DeveloperID int64 `gorm:"column:developer_id;not null;comment:Developer ID" json:"developer_id"` // Developer ID
AppID int64 `gorm:"column:app_id;not null;comment:Application ID" json:"app_id"` // Application ID
IconURI string `gorm:"column:icon_uri;not null;comment:Icon URI" json:"icon_uri"` // Icon URI
ServerURL string `gorm:"column:server_url;not null;comment:Server URL" json:"server_url"` // Server URL
PluginType int32 `gorm:"column:plugin_type;not null;comment:Plugin Type, 1:http, 6:local" json:"plugin_type"` // Plugin Type, 1:http, 6:local
CreatedAt int64 `gorm:"column:created_at;not null;autoCreateTime:milli;comment:Create Time in Milliseconds" json:"created_at"` // Create Time in Milliseconds
UpdatedAt int64 `gorm:"column:updated_at;not null;autoUpdateTime:milli;comment:Update Time in Milliseconds" json:"updated_at"` // Update Time in Milliseconds
Version string `gorm:"column:version;not null;comment:Plugin Version, e.g. v1.0.0" json:"version"` // Plugin Version, e.g. v1.0.0
VersionDesc string `gorm:"column:version_desc;comment:Plugin Version Description" json:"version_desc"` // Plugin Version Description
Manifest *model.PluginManifest `gorm:"column:manifest;comment:Plugin Manifest;serializer:json" json:"manifest"` // Plugin Manifest
OpenapiDoc *model.Openapi3T `gorm:"column:openapi_doc;comment:OpenAPI Document, only stores the root;serializer:json" json:"openapi_doc"` // OpenAPI Document, only stores the root
Source int32 `gorm:"column:source;not null;comment:plugin source 1 from saas 0 default" json:"source"` // plugin source 1 from saas 0 default
Ext map[string]interface{} `gorm:"column:ext;comment:extra ;serializer:json" json:"ext"` // extra
}
// TableName Plugin's table name

View File

@ -1,3 +1,19 @@
/*
* 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 gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
@ -13,20 +29,22 @@ const TableNamePluginVersion = "plugin_version"
// PluginVersion Plugin Version
type PluginVersion struct {
ID int64 `gorm:"column:id;primaryKey;comment:Primary Key ID" json:"id"` // Primary Key ID
SpaceID int64 `gorm:"column:space_id;not null;comment:Space ID" json:"space_id"` // Space ID
DeveloperID int64 `gorm:"column:developer_id;not null;comment:Developer ID" json:"developer_id"` // Developer ID
PluginID int64 `gorm:"column:plugin_id;not null;comment:Plugin ID" json:"plugin_id"` // Plugin ID
AppID int64 `gorm:"column:app_id;not null;comment:Application ID" json:"app_id"` // Application ID
IconURI string `gorm:"column:icon_uri;not null;comment:Icon URI" json:"icon_uri"` // Icon URI
ServerURL string `gorm:"column:server_url;not null;comment:Server URL" json:"server_url"` // Server URL
PluginType int32 `gorm:"column:plugin_type;not null;comment:Plugin Type, 1:http, 6:local" json:"plugin_type"` // Plugin Type, 1:http, 6:local
Version string `gorm:"column:version;not null;comment:Plugin Version, e.g. v1.0.0" json:"version"` // Plugin Version, e.g. v1.0.0
VersionDesc string `gorm:"column:version_desc;comment:Plugin Version Description" json:"version_desc"` // Plugin Version Description
Manifest *model.PluginManifest `gorm:"column:manifest;comment:Plugin Manifest;serializer:json" json:"manifest"` // Plugin Manifest
OpenapiDoc *model.Openapi3T `gorm:"column:openapi_doc;comment:OpenAPI Document, only stores the root;serializer:json" json:"openapi_doc"` // OpenAPI Document, only stores the root
CreatedAt int64 `gorm:"column:created_at;not null;autoCreateTime:milli;comment:Create Time in Milliseconds" json:"created_at"` // Create Time in Milliseconds
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time" json:"deleted_at"` // Delete Time
ID int64 `gorm:"column:id;primaryKey;comment:Primary Key ID" json:"id"` // Primary Key ID
SpaceID int64 `gorm:"column:space_id;not null;comment:Space ID" json:"space_id"` // Space ID
DeveloperID int64 `gorm:"column:developer_id;not null;comment:Developer ID" json:"developer_id"` // Developer ID
PluginID int64 `gorm:"column:plugin_id;not null;comment:Plugin ID" json:"plugin_id"` // Plugin ID
AppID int64 `gorm:"column:app_id;not null;comment:Application ID" json:"app_id"` // Application ID
IconURI string `gorm:"column:icon_uri;not null;comment:Icon URI" json:"icon_uri"` // Icon URI
ServerURL string `gorm:"column:server_url;not null;comment:Server URL" json:"server_url"` // Server URL
PluginType int32 `gorm:"column:plugin_type;not null;comment:Plugin Type, 1:http, 6:local" json:"plugin_type"` // Plugin Type, 1:http, 6:local
Version string `gorm:"column:version;not null;comment:Plugin Version, e.g. v1.0.0" json:"version"` // Plugin Version, e.g. v1.0.0
VersionDesc string `gorm:"column:version_desc;comment:Plugin Version Description" json:"version_desc"` // Plugin Version Description
Manifest *model.PluginManifest `gorm:"column:manifest;comment:Plugin Manifest;serializer:json" json:"manifest"` // Plugin Manifest
OpenapiDoc *model.Openapi3T `gorm:"column:openapi_doc;comment:OpenAPI Document, only stores the root;serializer:json" json:"openapi_doc"` // OpenAPI Document, only stores the root
Source int32 `gorm:"column:source;not null;comment:plugin source 1 from saas 0 default" json:"source"` // plugin source 1 from saas 0 default
Ext map[string]interface{} `gorm:"column:ext;comment:extra ;serializer:json" json:"ext"` // extra
CreatedAt int64 `gorm:"column:created_at;not null;autoCreateTime:milli;comment:Create Time in Milliseconds" json:"created_at"` // Create Time in Milliseconds
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time" json:"deleted_at"` // Delete Time
}
// TableName PluginVersion's table name

View File

@ -1,3 +1,19 @@
/*
* 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 gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
@ -19,6 +35,8 @@ type Tool struct {
Method string `gorm:"column:method;not null;comment:HTTP Request Method" json:"method"` // HTTP Request Method
Operation *model.Openapi3Operation `gorm:"column:operation;comment:Tool Openapi Operation Schema;serializer:json" json:"operation"` // Tool Openapi Operation Schema
ActivatedStatus int32 `gorm:"column:activated_status;not null;comment:0:activated; 1:deactivated" json:"activated_status"` // 0:activated; 1:deactivated
Source int32 `gorm:"column:source;not null;comment:tool source 1 coze saas 0 default" json:"source"` // tool source 1 coze saas 0 default
Ext map[string]interface{} `gorm:"column:ext;comment:extra;serializer:json" json:"ext"` // extra
}
// TableName Tool's table name

View File

@ -1,3 +1,19 @@
/*
* 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 gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
@ -22,6 +38,8 @@ type ToolVersion struct {
Operation *model.Openapi3Operation `gorm:"column:operation;comment:Tool Openapi Operation Schema;serializer:json" json:"operation"` // Tool Openapi Operation Schema
CreatedAt int64 `gorm:"column:created_at;not null;autoCreateTime:milli;comment:Create Time in Milliseconds" json:"created_at"` // Create Time in Milliseconds
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time" json:"deleted_at"` // Delete Time
Source int32 `gorm:"column:source;not null;comment:tool source 1 coze saas 0 default" json:"source"` // tool source 1 coze saas 0 default
Ext map[string]interface{} `gorm:"column:ext;comment:extra;serializer:json" json:"ext"` // extra
}
// TableName ToolVersion's table name

View File

@ -25,6 +25,7 @@ import (
"gorm.io/gen/field"
"gorm.io/gorm"
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
plugin_develop_common "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop/common"
pluginModel "github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/model"
"github.com/coze-dev/coze-studio/backend/domain/plugin/dto"
@ -63,6 +64,8 @@ func (p pluginPO) ToDO() *entity.PluginInfo {
VersionDesc: &p.VersionDesc,
Manifest: p.Manifest,
OpenapiDoc: p.OpenapiDoc,
Source: bot_common.PluginSourcePtr(bot_common.PluginSource(p.Source)),
Extra: p.Ext,
})
}

View File

@ -24,6 +24,7 @@ import (
"gorm.io/gen/field"
"gorm.io/gorm"
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
plugin_develop_common "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop/common"
pluginModel "github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/model"
"github.com/coze-dev/coze-studio/backend/domain/plugin/dto"
@ -62,6 +63,8 @@ func (p pluginVersionPO) ToDO() *entity.PluginInfo {
VersionDesc: &p.VersionDesc,
Manifest: p.Manifest,
OpenapiDoc: p.OpenapiDoc,
Source: bot_common.PluginSourcePtr(bot_common.PluginSource(p.Source)),
Extra: p.Ext,
})
}

View File

@ -1,3 +1,19 @@
/*
* 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 gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
@ -40,6 +56,8 @@ func newPlugin(db *gorm.DB, opts ...gen.DOOption) plugin {
_plugin.VersionDesc = field.NewString(tableName, "version_desc")
_plugin.Manifest = field.NewField(tableName, "manifest")
_plugin.OpenapiDoc = field.NewField(tableName, "openapi_doc")
_plugin.Source = field.NewInt32(tableName, "source")
_plugin.Ext = field.NewField(tableName, "ext")
_plugin.fillFieldMap()
@ -64,6 +82,8 @@ type plugin struct {
VersionDesc field.String // Plugin Version Description
Manifest field.Field // Plugin Manifest
OpenapiDoc field.Field // OpenAPI Document, only stores the root
Source field.Int32 // plugin source 1 from saas 0 default
Ext field.Field // extra
fieldMap map[string]field.Expr
}
@ -93,6 +113,8 @@ func (p *plugin) updateTableName(table string) *plugin {
p.VersionDesc = field.NewString(table, "version_desc")
p.Manifest = field.NewField(table, "manifest")
p.OpenapiDoc = field.NewField(table, "openapi_doc")
p.Source = field.NewInt32(table, "source")
p.Ext = field.NewField(table, "ext")
p.fillFieldMap()
@ -109,7 +131,7 @@ func (p *plugin) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
}
func (p *plugin) fillFieldMap() {
p.fieldMap = make(map[string]field.Expr, 13)
p.fieldMap = make(map[string]field.Expr, 15)
p.fieldMap["id"] = p.ID
p.fieldMap["space_id"] = p.SpaceID
p.fieldMap["developer_id"] = p.DeveloperID
@ -123,6 +145,8 @@ func (p *plugin) fillFieldMap() {
p.fieldMap["version_desc"] = p.VersionDesc
p.fieldMap["manifest"] = p.Manifest
p.fieldMap["openapi_doc"] = p.OpenapiDoc
p.fieldMap["source"] = p.Source
p.fieldMap["ext"] = p.Ext
}
func (p plugin) clone(db *gorm.DB) plugin {

View File

@ -1,3 +1,19 @@
/*
* 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 gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
@ -39,6 +55,8 @@ func newPluginVersion(db *gorm.DB, opts ...gen.DOOption) pluginVersion {
_pluginVersion.VersionDesc = field.NewString(tableName, "version_desc")
_pluginVersion.Manifest = field.NewField(tableName, "manifest")
_pluginVersion.OpenapiDoc = field.NewField(tableName, "openapi_doc")
_pluginVersion.Source = field.NewInt32(tableName, "source")
_pluginVersion.Ext = field.NewField(tableName, "ext")
_pluginVersion.CreatedAt = field.NewInt64(tableName, "created_at")
_pluginVersion.DeletedAt = field.NewField(tableName, "deleted_at")
@ -64,6 +82,8 @@ type pluginVersion struct {
VersionDesc field.String // Plugin Version Description
Manifest field.Field // Plugin Manifest
OpenapiDoc field.Field // OpenAPI Document, only stores the root
Source field.Int32 // plugin source 1 from saas 0 default
Ext field.Field // extra
CreatedAt field.Int64 // Create Time in Milliseconds
DeletedAt field.Field // Delete Time
@ -94,6 +114,8 @@ func (p *pluginVersion) updateTableName(table string) *pluginVersion {
p.VersionDesc = field.NewString(table, "version_desc")
p.Manifest = field.NewField(table, "manifest")
p.OpenapiDoc = field.NewField(table, "openapi_doc")
p.Source = field.NewInt32(table, "source")
p.Ext = field.NewField(table, "ext")
p.CreatedAt = field.NewInt64(table, "created_at")
p.DeletedAt = field.NewField(table, "deleted_at")
@ -112,7 +134,7 @@ func (p *pluginVersion) GetFieldByName(fieldName string) (field.OrderExpr, bool)
}
func (p *pluginVersion) fillFieldMap() {
p.fieldMap = make(map[string]field.Expr, 14)
p.fieldMap = make(map[string]field.Expr, 16)
p.fieldMap["id"] = p.ID
p.fieldMap["space_id"] = p.SpaceID
p.fieldMap["developer_id"] = p.DeveloperID
@ -125,6 +147,8 @@ func (p *pluginVersion) fillFieldMap() {
p.fieldMap["version_desc"] = p.VersionDesc
p.fieldMap["manifest"] = p.Manifest
p.fieldMap["openapi_doc"] = p.OpenapiDoc
p.fieldMap["source"] = p.Source
p.fieldMap["ext"] = p.Ext
p.fieldMap["created_at"] = p.CreatedAt
p.fieldMap["deleted_at"] = p.DeletedAt
}

View File

@ -1,3 +1,19 @@
/*
* 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 gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
@ -36,6 +52,8 @@ func newTool(db *gorm.DB, opts ...gen.DOOption) tool {
_tool.Method = field.NewString(tableName, "method")
_tool.Operation = field.NewField(tableName, "operation")
_tool.ActivatedStatus = field.NewInt32(tableName, "activated_status")
_tool.Source = field.NewInt32(tableName, "source")
_tool.Ext = field.NewField(tableName, "ext")
_tool.fillFieldMap()
@ -56,6 +74,8 @@ type tool struct {
Method field.String // HTTP Request Method
Operation field.Field // Tool Openapi Operation Schema
ActivatedStatus field.Int32 // 0:activated; 1:deactivated
Source field.Int32 // tool source 1 coze saas 0 default
Ext field.Field // extra
fieldMap map[string]field.Expr
}
@ -81,6 +101,8 @@ func (t *tool) updateTableName(table string) *tool {
t.Method = field.NewString(table, "method")
t.Operation = field.NewField(table, "operation")
t.ActivatedStatus = field.NewInt32(table, "activated_status")
t.Source = field.NewInt32(table, "source")
t.Ext = field.NewField(table, "ext")
t.fillFieldMap()
@ -97,7 +119,7 @@ func (t *tool) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
}
func (t *tool) fillFieldMap() {
t.fieldMap = make(map[string]field.Expr, 9)
t.fieldMap = make(map[string]field.Expr, 11)
t.fieldMap["id"] = t.ID
t.fieldMap["plugin_id"] = t.PluginID
t.fieldMap["created_at"] = t.CreatedAt
@ -107,6 +129,8 @@ func (t *tool) fillFieldMap() {
t.fieldMap["method"] = t.Method
t.fieldMap["operation"] = t.Operation
t.fieldMap["activated_status"] = t.ActivatedStatus
t.fieldMap["source"] = t.Source
t.fieldMap["ext"] = t.Ext
}
func (t tool) clone(db *gorm.DB) tool {

View File

@ -1,3 +1,19 @@
/*
* 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 gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
@ -36,6 +52,8 @@ func newToolVersion(db *gorm.DB, opts ...gen.DOOption) toolVersion {
_toolVersion.Operation = field.NewField(tableName, "operation")
_toolVersion.CreatedAt = field.NewInt64(tableName, "created_at")
_toolVersion.DeletedAt = field.NewField(tableName, "deleted_at")
_toolVersion.Source = field.NewInt32(tableName, "source")
_toolVersion.Ext = field.NewField(tableName, "ext")
_toolVersion.fillFieldMap()
@ -56,6 +74,8 @@ type toolVersion struct {
Operation field.Field // Tool Openapi Operation Schema
CreatedAt field.Int64 // Create Time in Milliseconds
DeletedAt field.Field // Delete Time
Source field.Int32 // tool source 1 coze saas 0 default
Ext field.Field // extra
fieldMap map[string]field.Expr
}
@ -81,6 +101,8 @@ func (t *toolVersion) updateTableName(table string) *toolVersion {
t.Operation = field.NewField(table, "operation")
t.CreatedAt = field.NewInt64(table, "created_at")
t.DeletedAt = field.NewField(table, "deleted_at")
t.Source = field.NewInt32(table, "source")
t.Ext = field.NewField(table, "ext")
t.fillFieldMap()
@ -97,7 +119,7 @@ func (t *toolVersion) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
}
func (t *toolVersion) fillFieldMap() {
t.fieldMap = make(map[string]field.Expr, 9)
t.fieldMap = make(map[string]field.Expr, 11)
t.fieldMap["id"] = t.ID
t.fieldMap["tool_id"] = t.ToolID
t.fieldMap["plugin_id"] = t.PluginID
@ -107,6 +129,8 @@ func (t *toolVersion) fillFieldMap() {
t.fieldMap["operation"] = t.Operation
t.fieldMap["created_at"] = t.CreatedAt
t.fieldMap["deleted_at"] = t.DeletedAt
t.fieldMap["source"] = t.Source
t.fieldMap["ext"] = t.Ext
}
func (t toolVersion) clone(db *gorm.DB) toolVersion {

View File

@ -24,6 +24,7 @@ import (
"gorm.io/gen/field"
"gorm.io/gorm"
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/consts"
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
"github.com/coze-dev/coze-studio/backend/domain/plugin/internal/dal/model"
@ -58,6 +59,9 @@ func (t toolPO) ToDO() *entity.ToolInfo {
Method: ptr.Of(t.Method),
Operation: t.Operation,
ActivatedStatus: ptr.Of(consts.ActivatedStatus(t.ActivatedStatus)),
Source: bot_common.PluginSourcePtr(bot_common.PluginSource(t.Source)),
Extra: t.Ext,
}
}

View File

@ -22,6 +22,7 @@ import (
"gorm.io/gorm"
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
pluginModel "github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/model"
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
"github.com/coze-dev/coze-studio/backend/domain/plugin/internal/dal/model"
@ -54,6 +55,9 @@ func (t toolVersionPO) ToDO() *entity.ToolInfo {
SubURL: &t.SubURL,
Method: ptr.Of(t.Method),
Operation: t.Operation,
Source: bot_common.PluginSourcePtr(bot_common.PluginSource(t.Source)),
Extra: t.Ext,
}
}

View File

@ -97,6 +97,19 @@ func (p *pluginServiceImpl) ListPluginProducts(ctx context.Context, req *dto.Lis
return plugins[i].GetRefProductID() < plugins[j].GetRefProductID()
})
// official plugins
officialPlugins, _, err := p.pluginRepo.ListCustomOnlinePlugins(ctx, 999999, dto.PageInfo{
Page: 1,
Size: 1000,
OrderByACS: ptr.Of(true),
SortBy:ptr.Of(dto.SortByCreatedAt),
})
if err != nil {
return nil, errorx.Wrapf(err, "ListCustomOnlinePlugins failed, spaceID=999999")
}
plugins = append(plugins, officialPlugins...)
return &dto.ListPluginProductsResponse{
Plugins: plugins,
Total: int64(len(plugins)),

View File

@ -21,9 +21,13 @@ import (
"encoding/json"
"fmt"
"strconv"
"strings"
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
pluginCommon "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop/common"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/consts"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/convert/api"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/model"
domainDto "github.com/coze-dev/coze-studio/backend/domain/plugin/dto"
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
@ -43,9 +47,14 @@ type CozePlugin struct {
UpdatedAt int64 `json:"updated_at"`
}
func (p *pluginServiceImpl) ListSaasPluginProducts(ctx context.Context, req *domainDto.ListPluginProductsRequest) (resp *domainDto.ListPluginProductsResponse, err error) {
plugins, err := p.fetchSaasPluginsFromCoze(ctx)
func (p *pluginServiceImpl) ListSaasPluginProducts(ctx context.Context, req *domainDto.ListSaasPluginProductsRequest) (resp *domainDto.ListPluginProductsResponse, err error) {
searchReq := &domainDto.SearchSaasPluginRequest{
PageNum: ptr.Of(int(*req.PageNum)),
PageSize: ptr.Of(int(*req.PageSize)),
Keyword: req.Keyword,
IsOfficial: req.IsOfficial,
}
plugins, hasMore,err := p.fetchSaasPluginsFromCoze(ctx, searchReq)
if err != nil {
return nil, errorx.Wrapf(err, "fetchSaasPluginsFromCoze failed")
}
@ -53,14 +62,166 @@ func (p *pluginServiceImpl) ListSaasPluginProducts(ctx context.Context, req *dom
return &domainDto.ListPluginProductsResponse{
Plugins: plugins,
Total: int64(len(plugins)),
HasMore: hasMore,
}, nil
}
func (p *pluginServiceImpl) BatchGetSaasPluginToolsInfo(ctx context.Context, pluginIDs []int64) (tools map[int64][]*entity.ToolInfo, err error) {
if len(pluginIDs) == 0 {
return make(map[int64][]*entity.ToolInfo), nil
}
client := saasapi.NewCozeAPIClient()
var idStrings []string
for _, id := range pluginIDs {
idStrings = append(idStrings, strconv.FormatInt(id, 10))
}
idsStr := strings.Join(idStrings, ",")
queryParams := map[string]interface{}{
"ids": idsStr,
}
resp, err := client.GetWithQuery(ctx, "/v1/plugins/mget", queryParams)
if err != nil {
return nil, errorx.Wrapf(err, "failed to call coze.cn /v1/plugins/mget API")
}
var apiResp struct {
Plugins []struct {
Tools []struct {
ToolID string `json:"tool_id"`
Description string `json:"description"`
InputSchema *domainDto.JsonSchema `json:"inputSchema"`
Name string `json:"name"`
OutputSchema *domainDto.JsonSchema `json:"outputSchema"`
} `json:"tools"`
McpJSON string `json:"mcp_json"`
} `json:"plugins"`
}
if err := json.Unmarshal(resp.Data, &apiResp); err != nil {
return nil, errorx.Wrapf(err, "failed to parse coze.cn API response")
}
result := make(map[int64][]*entity.ToolInfo)
for i, plugin := range apiResp.Plugins {
if i >= len(pluginIDs) {
break
}
pluginID := pluginIDs[i]
toolInfos := make([]*entity.ToolInfo, 0, len(plugin.Tools))
for _, tool := range plugin.Tools {
openapi3Operation, err := api.APIParamsToOpenapiOperation(convertFromJsonSchema(tool.InputSchema), convertFromJsonSchema(tool.OutputSchema))
if err != nil {
return nil, errorx.Wrapf(err, "failed to convert input schema to openapi operation parameters")
}
openapi3Operation.OperationID = tool.Name
openapi3Operation.Summary = tool.Description
operation := &model.Openapi3Operation{
Operation: openapi3Operation,
}
id, err := strconv.ParseInt(tool.ToolID, 10, 64)
if err != nil {
return nil, errorx.Wrapf(err, "failed to parse tool ID %s", tool.ToolID)
}
toolInfo := &entity.ToolInfo{
ID: id,
PluginID: pluginID,
Operation: operation,
Source: ptr.Of(bot_common.PluginSource_FromSaas),
}
toolInfos = append(toolInfos, toolInfo)
}
result[pluginID] = toolInfos
}
logs.CtxInfof(ctx, "fetched SaaS plugin tools info from coze.cn, pluginIDs: %v, total tools: %d", pluginIDs, len(result))
return result, nil
}
func mapJsonSchemaTypeToParameterType(schemaType domainDto.JsonSchemaType) pluginCommon.ParameterType {
switch schemaType {
case domainDto.JsonSchemaType_STRING:
return pluginCommon.ParameterType_String
case domainDto.JsonSchemaType_NUMBER:
return pluginCommon.ParameterType_Number
case domainDto.JsonSchemaType_INTEGER:
return pluginCommon.ParameterType_Integer
case domainDto.JsonSchemaType_BOOLEAN:
return pluginCommon.ParameterType_Bool
case domainDto.JsonSchemaType_OBJECT:
return pluginCommon.ParameterType_Object
case domainDto.JsonSchemaType_ARRAY:
return pluginCommon.ParameterType_Array
default:
return pluginCommon.ParameterType_String
}
}
func convertFromJsonSchema(schema *domainDto.JsonSchema) []*pluginCommon.APIParameter {
if schema == nil {
return []*pluginCommon.APIParameter{}
}
var parameters []*pluginCommon.APIParameter
// Handle object type with properties
if schema.Type == domainDto.JsonSchemaType_OBJECT && len(schema.Properties) > 0 {
// Create a set of required fields for quick lookup
requiredFields := make(map[string]bool)
for _, field := range schema.Required {
requiredFields[field] = true
}
// Convert each property to a parameter
for name, propSchema := range schema.Properties {
if propSchema == nil {
continue
}
param := &pluginCommon.APIParameter{
Name: name,
Desc: propSchema.Description,
IsRequired: requiredFields[name],
Type: mapJsonSchemaTypeToParameterType(propSchema.Type),
Location: pluginCommon.ParameterLocation_Body,
}
// Handle nested object type
if propSchema.Type == domainDto.JsonSchemaType_OBJECT && len(propSchema.Properties) > 0 {
param.SubParameters = convertFromJsonSchema(propSchema)
}
// Handle array type
if propSchema.Type == domainDto.JsonSchemaType_ARRAY && propSchema.Items != nil {
param.Type = (mapJsonSchemaTypeToParameterType(propSchema.Items.Type))
if propSchema.Items.Type == domainDto.JsonSchemaType_OBJECT && len(propSchema.Items.Properties) > 0 {
param.SubParameters = convertFromJsonSchema(propSchema.Items)
}
}
parameters = append(parameters, param)
}
}
return parameters
}
func (p *pluginServiceImpl) fetchSaasPluginsFromCoze(ctx context.Context, searchReq *domainDto.SearchSaasPluginRequest) ([]*entity.PluginInfo, bool, error) {
func (p *pluginServiceImpl) fetchSaasPluginsFromCoze(ctx context.Context) ([]*entity.PluginInfo, error) {
searchReq := &domainDto.SearchSaasPluginRequest{}
searchResp, err := p.searchSaasPlugin(ctx, searchReq)
if err != nil {
return nil, errorx.Wrapf(err, "failed to search SaaS plugins")
return nil, false, errorx.Wrapf(err, "failed to search SaaS plugins")
}
if searchResp == nil || searchResp.Data == nil {
return nil, false, nil
}
plugins := make([]*entity.PluginInfo, 0, len(searchResp.Data.Items))
@ -69,9 +230,7 @@ func (p *pluginServiceImpl) fetchSaasPluginsFromCoze(ctx context.Context) ([]*en
plugins = append(plugins, plugin)
}
logs.CtxInfof(ctx, "fetched %d SaaS plugins from coze.cn", len(plugins))
return plugins, nil
return plugins, searchResp.Data.HasMore, nil
}
func convertSaasPluginItemToEntity(item *domainDto.SaasPluginItem) *entity.PluginInfo {
@ -81,11 +240,8 @@ func convertSaasPluginItemToEntity(item *domainDto.SaasPluginItem) *entity.Plugi
metaInfo := item.MetaInfo
var pluginID int64
if id, err := strconv.ParseInt(metaInfo.ProductID, 10, 64); err == nil {
if id, err := strconv.ParseInt(metaInfo.EntityID, 10, 64); err == nil {
pluginID = id
} else {
// 如果ID不是数字使用简单的hash算法生成ID
pluginID = int64(simpleHash(metaInfo.ProductID))
}
// 创建插件清单
@ -124,8 +280,6 @@ func convertCozePluginToEntity(cozePlugin CozePlugin) *entity.PluginInfo {
var pluginID int64
if id, err := strconv.ParseInt(cozePlugin.ID, 10, 64); err == nil {
pluginID = id
} else {
pluginID = int64(simpleHash(cozePlugin.ID))
}
manifest := &model.PluginManifest{
@ -159,14 +313,6 @@ func convertCozePluginToEntity(cozePlugin CozePlugin) *entity.PluginInfo {
return entity.NewPluginInfo(pluginInfo)
}
func simpleHash(s string) uint32 {
var hash uint32 = 5381
for _, c := range s {
hash = ((hash << 5) + hash) + uint32(c)
}
return hash
}
func (p *pluginServiceImpl) GetSaasPluginInfo(ctx context.Context, pluginID int64) (plugin *entity.PluginInfo, err error) {
client := saasapi.NewCozeAPIClient()

View File

@ -22,6 +22,7 @@ import (
"github.com/stretchr/testify/assert"
pluginCommon "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop/common"
domainDto "github.com/coze-dev/coze-studio/backend/domain/plugin/dto"
)
@ -167,4 +168,282 @@ func TestSearchSaasPluginResponse_WithAllNewFields(t *testing.T) {
assert.NotNil(t, item.PluginInfo)
assert.Equal(t, 5, item.PluginInfo.FavoriteCount)
assert.Equal(t, int64(100), item.PluginInfo.CallCount)
}
func TestJsonSchemaTypeUnmarshaling(t *testing.T) {
// Test JSON data with inputSchema containing type field
jsonData := `{
"plugins": [{
"tools": [{
"tool_id": "7379227817307029513",
"description": "当你需要获取网页、pdf、doc、docx、xlsx、csv、text 内容时,使用此工具",
"name": "LinkReaderPlugin",
"inputSchema": {
"required": ["url"],
"properties": {
"need_image_url": {
"description": "是否需要返回图片url",
"type": "boolean"
},
"url": {
"description": "网页url、pdf url、docx url、csv url、 xlsx url。",
"type": "string"
}
},
"type": "object"
},
"outputSchema": {
"properties": {
"data": {
"properties": {
"content": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
}]
}]
}`
var apiResp struct {
Plugins []struct {
Tools []struct {
ToolID string `json:"tool_id"`
Description string `json:"description"`
InputSchema *domainDto.JsonSchema `json:"inputSchema"`
Name string `json:"name"`
OutputSchema *domainDto.JsonSchema `json:"outputSchema"`
} `json:"tools"`
} `json:"plugins"`
}
err := json.Unmarshal([]byte(jsonData), &apiResp)
assert.NoError(t, err)
// Verify that we have the expected structure
assert.Len(t, apiResp.Plugins, 1)
assert.Len(t, apiResp.Plugins[0].Tools, 1)
tool := apiResp.Plugins[0].Tools[0]
assert.Equal(t, "7379227817307029513", tool.ToolID)
assert.Equal(t, "LinkReaderPlugin", tool.Name)
// Verify InputSchema type field is correctly parsed
assert.NotNil(t, tool.InputSchema)
assert.Equal(t, domainDto.JsonSchemaType_OBJECT, tool.InputSchema.Type)
assert.Len(t, tool.InputSchema.Required, 1)
assert.Equal(t, "url", tool.InputSchema.Required[0])
// Verify properties are correctly parsed with their types
assert.NotNil(t, tool.InputSchema.Properties)
assert.Len(t, tool.InputSchema.Properties, 2)
urlProp := tool.InputSchema.Properties["url"]
assert.NotNil(t, urlProp)
assert.Equal(t, domainDto.JsonSchemaType_STRING, urlProp.Type)
assert.Equal(t, "网页url、pdf url、docx url、csv url、 xlsx url。", urlProp.Description)
needImageProp := tool.InputSchema.Properties["need_image_url"]
assert.NotNil(t, needImageProp)
assert.Equal(t, domainDto.JsonSchemaType_BOOLEAN, needImageProp.Type)
assert.Equal(t, "是否需要返回图片url", needImageProp.Description)
// Verify OutputSchema type field is correctly parsed
assert.NotNil(t, tool.OutputSchema)
assert.Equal(t, domainDto.JsonSchemaType_OBJECT, tool.OutputSchema.Type)
}
func TestConvertFromJsonSchemaWithFixedType(t *testing.T) {
// Create a JsonSchema with the type field properly set
schema := &domainDto.JsonSchema{
Type: domainDto.JsonSchemaType_OBJECT,
Properties: map[string]*domainDto.JsonSchema{
"url": {
Type: domainDto.JsonSchemaType_STRING,
Description: "网页url",
},
"need_image_url": {
Type: domainDto.JsonSchemaType_BOOLEAN,
Description: "是否需要返回图片url",
},
},
Required: []string{"url"},
}
// Test the convertFromJsonSchema function
parameters := convertFromJsonSchema(schema)
// Debug: print the actual values
t.Logf("Number of parameters: %d", len(parameters))
for i, param := range parameters {
t.Logf("Parameter %d: Name=%s, Location=%d, Type=%d", i, param.Name, param.Location, param.Type)
}
// Verify that parameters are correctly generated
assert.Len(t, parameters, 2)
// Find the url parameter
var urlParam, imageParam *pluginCommon.APIParameter
for _, param := range parameters {
if param.Name == "url" {
urlParam = param
} else if param.Name == "need_image_url" {
imageParam = param
}
}
// Verify url parameter
assert.NotNil(t, urlParam)
assert.Equal(t, "url", urlParam.Name)
assert.Equal(t, "网页url", urlParam.Desc)
assert.True(t, urlParam.IsRequired)
assert.Equal(t, pluginCommon.ParameterType_String, urlParam.Type)
assert.Equal(t, pluginCommon.ParameterLocation_Body, urlParam.Location)
// Verify need_image_url parameter
assert.NotNil(t, imageParam)
assert.Equal(t, "need_image_url", imageParam.Name)
assert.Equal(t, "是否需要返回图片url", imageParam.Desc)
assert.False(t, imageParam.IsRequired) // not in required array
assert.Equal(t, pluginCommon.ParameterType_Bool, imageParam.Type)
assert.Equal(t, pluginCommon.ParameterLocation_Body, imageParam.Location)
}
func TestBatchGetSaasPluginToolsInfoIntegration(t *testing.T) {
// This test simulates the original issue scenario
// Create mock response data similar to what was provided in the issue
respData := `{
"plugins": [{
"tools": [{
"tool_id": "7379227817307029513",
"description": "当你需要获取网页、pdf、doc、docx、xlsx、csv、text 内容时使用此工具可以获取url链接下的标题和内容。由于个别网站自身站点限制无法获取网页内容。",
"name": "LinkReaderPlugin",
"inputSchema": {
"required": ["url"],
"properties": {
"need_image_url": {
"description": "是否需要返回图片url",
"type": "boolean"
},
"url": {
"description": "网页url、pdf url、docx url、csv url、 xlsx url。",
"type": "string"
}
},
"type": "object"
},
"outputSchema": {
"properties": {
"data": {
"properties": {
"images": {
"items": {
"properties": {
"title": {"type": "string"},
"url": {"type": "string"},
"width": {"type": "integer"},
"alt": {"type": "string"},
"height": {"type": "integer"}
},
"type": "object"
},
"type": "array"
},
"title": {"type": "string"},
"content": {"type": "string"}
},
"type": "object"
},
"err_msg": {
"description": "错误信息",
"type": "string"
},
"error_code": {
"description": "错误码",
"type": "string"
},
"error_msg": {
"description": "错误信息",
"type": "string"
},
"message": {
"description": "错误信息",
"type": "string"
},
"pdf_content": {
"description": "pdf的内容",
"type": "string"
},
"code": {
"description": "错误码",
"type": "integer"
}
},
"type": "object"
}
}]
}]
}`
// Simulate the unmarshaling process that happens in BatchGetSaasPluginToolsInfo
var apiResp struct {
Plugins []struct {
Tools []struct {
ToolID string `json:"tool_id"`
Description string `json:"description"`
InputSchema *domainDto.JsonSchema `json:"inputSchema"`
Name string `json:"name"`
OutputSchema *domainDto.JsonSchema `json:"outputSchema"`
} `json:"tools"`
McpJSON string `json:"mcp_json"`
} `json:"plugins"`
}
err := json.Unmarshal([]byte(respData), &apiResp)
assert.NoError(t, err)
// Verify the structure is correctly parsed
assert.Len(t, apiResp.Plugins, 1)
assert.Len(t, apiResp.Plugins[0].Tools, 1)
tool := apiResp.Plugins[0].Tools[0]
// Verify InputSchema type is correctly parsed (this was the original issue)
assert.NotNil(t, tool.InputSchema)
assert.Equal(t, domainDto.JsonSchemaType_OBJECT, tool.InputSchema.Type)
// Now test the convertFromJsonSchema function with the parsed schema
parameters := convertFromJsonSchema(tool.InputSchema)
// This should NOT be empty anymore (this was the original problem)
assert.NotEmpty(t, parameters)
assert.Len(t, parameters, 2)
// Verify the parameters are correctly generated
paramMap := make(map[string]*pluginCommon.APIParameter)
for _, param := range parameters {
paramMap[param.Name] = param
}
// Check url parameter
urlParam := paramMap["url"]
assert.NotNil(t, urlParam)
assert.Equal(t, "url", urlParam.Name)
assert.True(t, urlParam.IsRequired)
assert.Equal(t, pluginCommon.ParameterType_String, urlParam.Type)
assert.Equal(t, pluginCommon.ParameterLocation_Body, urlParam.Location)
assert.Equal(t, "网页url、pdf url、docx url、csv url、 xlsx url。", urlParam.Desc)
// Check need_image_url parameter
imageParam := paramMap["need_image_url"]
assert.NotNil(t, imageParam)
assert.Equal(t, "need_image_url", imageParam.Name)
assert.False(t, imageParam.IsRequired)
assert.Equal(t, pluginCommon.ParameterType_Bool, imageParam.Type)
assert.Equal(t, pluginCommon.ParameterLocation_Body, imageParam.Location)
assert.Equal(t, "是否需要返回图片url", imageParam.Desc)
}

View File

@ -80,7 +80,8 @@ type PluginService interface {
GetOAuthStatus(ctx context.Context, userID, pluginID int64) (resp *dto.GetOAuthStatusResponse, err error)
GetAgentPluginsOAuthStatus(ctx context.Context, userID, agentID int64) (status []*dto.AgentPluginOAuthStatus, err error)
//Saas Plugin Product
ListSaasPluginProducts(ctx context.Context, req *dto.ListPluginProductsRequest) (resp *dto.ListPluginProductsResponse, err error)
ListSaasPluginProducts(ctx context.Context, req *dto.ListSaasPluginProductsRequest) (resp *dto.ListPluginProductsResponse, err error)
BatchGetSaasPluginToolsInfo(ctx context.Context, pluginIDs []int64) (tools map[int64][]*entity.ToolInfo, err error)
GetSaasPluginInfo(ctx context.Context, pluginID int64) (plugin *entity.PluginInfo, err error)
ListSaasPluginCategories(ctx context.Context, req *dto.ListPluginCategoriesRequest) (resp *dto.ListPluginCategoriesResponse, err error)

View File

@ -31,12 +31,14 @@ import (
"github.com/go-resty/resty/v2"
"github.com/tidwall/sjson"
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
pluginConsts "github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/consts"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/model"
"github.com/coze-dev/coze-studio/backend/domain/plugin/internal/encoder"
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
"github.com/coze-dev/coze-studio/backend/pkg/i18n"
"github.com/coze-dev/coze-studio/backend/pkg/lang/conv"
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
"github.com/coze-dev/coze-studio/backend/pkg/logs"
"github.com/coze-dev/coze-studio/backend/types/consts"
@ -156,6 +158,10 @@ func (h *httpCallImpl) buildHTTPRequest(ctx context.Context, args *InvocationArg
func (h *httpCallImpl) injectAuthInfo(ctx context.Context, httpReq *http.Request, args *InvocationArgs) (errMsg string, err error) {
if ptr.From(args.Tool.Source) == bot_common.PluginSource_FromSaas {
return h.injectCozeSaasAPIToken(ctx, httpReq)
}
if args.AuthInfo.MetaInfo.Type == pluginConsts.AuthzTypeOfNone {
return "", nil
}
@ -279,6 +285,17 @@ func (h *httpCallImpl) buildRequestBody(ctx context.Context, op *model.Openapi3O
return body, contentType, nil
}
func(h *httpCallImpl) injectCozeSaasAPIToken (ctx context.Context, httpReq *http.Request) (errMsg string, err error){
// apiToken := os.Getenv(consts.CozeSaasAPIKey)
apiToken := "pat_OjlRXGYdXDLHDv10dZuav02A7SomHZkXTjx0fbZ9xUDIrssE7tZ07gI2TzABBQ7M"
if apiToken == "" {
return "", fmt.Errorf("coze saas api token is empty")
}
httpReq.Header.Set("Authorization", "Bearer "+apiToken)
return "", nil
}
func (h *httpCallImpl) injectServiceAPIToken(ctx context.Context, httpReq *http.Request, authInfo *model.AuthV2) (errMsg string, err error) {
if authInfo.SubType == pluginConsts.AuthzSubTypeOfServiceAPIToken {
authOfAPIToken := authInfo.AuthOfAPIToken

View File

@ -216,7 +216,7 @@ func (c *CozeAPIClient) requestWithQuery(ctx context.Context, method, path strin
// Add API key if available
if c.APIKey != "" {
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.APIKey))
req.Header.Set("X-TT-ENV", "ppe_cozemcpserver")
req.Header.Set("X-TT-ENV", "ppe_cozeopenmcp")
req.Header.Set("X-USE-PPE", "1")
}

View File

@ -82,6 +82,7 @@ var path2Table2Columns2Model = map[string]map[string]map[string]any{
"plugin": {
"manifest": &plugin.PluginManifest{},
"openapi_doc": &plugin.Openapi3T{},
"ext": map[string]any{},
},
"plugin_draft": {
"manifest": &plugin.PluginManifest{},
@ -90,6 +91,7 @@ var path2Table2Columns2Model = map[string]map[string]map[string]any{
"plugin_version": {
"manifest": &plugin.PluginManifest{},
"openapi_doc": &plugin.Openapi3T{},
"ext": map[string]any{},
},
"agent_tool_draft": {
"operation": &plugin.Openapi3Operation{},
@ -99,12 +101,14 @@ var path2Table2Columns2Model = map[string]map[string]map[string]any{
},
"tool": {
"operation": &plugin.Openapi3Operation{},
"ext": map[string]any{},
},
"tool_draft": {
"operation": &plugin.Openapi3Operation{},
},
"tool_version": {
"operation": &plugin.Openapi3Operation{},
"ext": map[string]any{},
},
"plugin_oauth_auth": {
"oauth_config": &plugin.OAuthAuthorizationCodeConfig{},

View File

@ -0,0 +1,8 @@
-- Modify "plugin" table
ALTER TABLE `opencoze`.`plugin` ADD COLUMN `source` tinyint NOT NULL DEFAULT 0 COMMENT "plugin source 1 from saas 0 default" AFTER `openapi_doc`, ADD COLUMN `ext` json NULL COMMENT "extra ";
-- Modify "plugin_version" table
ALTER TABLE `opencoze`.`plugin_version` ADD COLUMN `source` tinyint NOT NULL DEFAULT 0 COMMENT "plugin source 1 from saas 0 default" AFTER `openapi_doc`, ADD COLUMN `ext` json NULL COMMENT "extra ";
-- Modify "tool" table
ALTER TABLE `opencoze`.`tool` ADD COLUMN `source` tinyint NOT NULL DEFAULT 0 COMMENT "tool source 1 coze saas 0 default" AFTER `activated_status`, ADD COLUMN `ext` json NULL COMMENT "extra";
-- Modify "tool_version" table
ALTER TABLE `opencoze`.`tool_version` ADD COLUMN `source` tinyint NOT NULL DEFAULT 0 COMMENT "tool source 1 coze saas 0 default" AFTER `deleted_at`, ADD COLUMN `ext` json NULL COMMENT "extra";

View File

@ -1,4 +1,4 @@
h1:pZ9P9pFFqnfVc+o3V1CJLD8Rv3WyFM+mSwqKk1GTRRs=
h1:lmHhy0psjXX5nxglqxAu8GAdbWV+CFENuOc1AyPR0B8=
20250703095335_initial.sql h1:/joaeUTMhXqAEc0KwsSve5+bYM0qPOp+9OizJtsRc+U=
20250703115304_update.sql h1:cbYo6Q6Lh96hB4hu5KW2Nn/Mr0VDpg7a1WPgpIb1SOc=
20250704040445_update.sql h1:QWmoPY//oQ+GFZwET9w/oAWa8mM0KVaD5G8Yiu9bMqY=
@ -12,3 +12,4 @@ h1:pZ9P9pFFqnfVc+o3V1CJLD8Rv3WyFM+mSwqKk1GTRRs=
20250812093734_update.sql h1:27fQaPt0LYi1dA7MABvERthVR4pj4MRWFgdRVR3cd6w=
20250813081543_update.sql h1:HyBPu1LVs8oiyABbZDU3fFW0n6MeC7qOpzcHWVkwNVc=
20250822060516_update.sql h1:KoL8FPXw5/JMsJMtJsoGFIc4wYHlngBudeYSz5o4iKU=
20250930034835_update.sql h1:VgI4ss8IylY7Y4LrOj9s9PFvC37YB0z4SlOlB+n++d0=