feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
400
backend/domain/plugin/service/service.go
Normal file
400
backend/domain/plugin/service/service.go
Normal file
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
|
||||
model "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/plugin"
|
||||
common "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop_common"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
//go:generate mockgen -destination ../../../internal/mock/domain/plugin/interface.go --package mockPlugin -source service.go
|
||||
type PluginService interface {
|
||||
// Draft Plugin
|
||||
CreateDraftPlugin(ctx context.Context, req *CreateDraftPluginRequest) (pluginID int64, err error)
|
||||
CreateDraftPluginWithCode(ctx context.Context, req *CreateDraftPluginWithCodeRequest) (resp *CreateDraftPluginWithCodeResponse, err error)
|
||||
GetDraftPlugin(ctx context.Context, pluginID int64) (plugin *entity.PluginInfo, err error)
|
||||
MGetDraftPlugins(ctx context.Context, pluginIDs []int64) (plugins []*entity.PluginInfo, err error)
|
||||
ListDraftPlugins(ctx context.Context, req *ListDraftPluginsRequest) (resp *ListDraftPluginsResponse, err error)
|
||||
UpdateDraftPlugin(ctx context.Context, plugin *UpdateDraftPluginRequest) (err error)
|
||||
UpdateDraftPluginWithCode(ctx context.Context, req *UpdateDraftPluginWithCodeRequest) (err error)
|
||||
DeleteDraftPlugin(ctx context.Context, pluginID int64) (err error)
|
||||
DeleteAPPAllPlugins(ctx context.Context, appID int64) (pluginIDs []int64, err error)
|
||||
GetAPPAllPlugins(ctx context.Context, appID int64) (plugins []*entity.PluginInfo, err error)
|
||||
|
||||
// Online Plugin
|
||||
PublishPlugin(ctx context.Context, req *PublishPluginRequest) (err error)
|
||||
PublishAPPPlugins(ctx context.Context, req *PublishAPPPluginsRequest) (resp *PublishAPPPluginsResponse, err error)
|
||||
GetOnlinePlugin(ctx context.Context, pluginID int64) (plugin *entity.PluginInfo, err error)
|
||||
MGetOnlinePlugins(ctx context.Context, pluginIDs []int64) (plugins []*entity.PluginInfo, err error)
|
||||
MGetPluginLatestVersion(ctx context.Context, pluginIDs []int64) (resp *MGetPluginLatestVersionResponse, err error)
|
||||
GetPluginNextVersion(ctx context.Context, pluginID int64) (version string, err error)
|
||||
MGetVersionPlugins(ctx context.Context, versionPlugins []entity.VersionPlugin) (plugins []*entity.PluginInfo, err error)
|
||||
ListCustomOnlinePlugins(ctx context.Context, spaceID int64, pageInfo entity.PageInfo) (plugins []*entity.PluginInfo, total int64, err error)
|
||||
|
||||
// Draft Tool
|
||||
MGetDraftTools(ctx context.Context, toolIDs []int64) (tools []*entity.ToolInfo, err error)
|
||||
UpdateDraftTool(ctx context.Context, req *UpdateToolDraftRequest) (err error)
|
||||
ConvertToOpenapi3Doc(ctx context.Context, req *ConvertToOpenapi3DocRequest) (resp *ConvertToOpenapi3DocResponse)
|
||||
CreateDraftToolsWithCode(ctx context.Context, req *CreateDraftToolsWithCodeRequest) (resp *CreateDraftToolsWithCodeResponse, err error)
|
||||
CheckPluginToolsDebugStatus(ctx context.Context, pluginID int64) (err error)
|
||||
|
||||
// Online Tool
|
||||
GetOnlineTool(ctx context.Context, toolID int64) (tool *entity.ToolInfo, err error)
|
||||
MGetOnlineTools(ctx context.Context, toolIDs []int64) (tools []*entity.ToolInfo, err error)
|
||||
MGetVersionTools(ctx context.Context, versionTools []entity.VersionTool) (tools []*entity.ToolInfo, err error)
|
||||
CopyPlugin(ctx context.Context, req *CopyPluginRequest) (resp *CopyPluginResponse, err error)
|
||||
MoveAPPPluginToLibrary(ctx context.Context, pluginID int64) (plugin *entity.PluginInfo, err error)
|
||||
|
||||
// Agent Tool
|
||||
BindAgentTools(ctx context.Context, agentID int64, toolIDs []int64) (err error)
|
||||
DuplicateDraftAgentTools(ctx context.Context, fromAgentID, toAgentID int64) (err error)
|
||||
GetDraftAgentToolByName(ctx context.Context, agentID int64, toolName string) (tool *entity.ToolInfo, err error)
|
||||
MGetAgentTools(ctx context.Context, req *MGetAgentToolsRequest) (tools []*entity.ToolInfo, err error)
|
||||
UpdateBotDefaultParams(ctx context.Context, req *UpdateBotDefaultParamsRequest) (err error)
|
||||
|
||||
PublishAgentTools(ctx context.Context, agentID int64, agentVersion string) (err error)
|
||||
|
||||
ExecuteTool(ctx context.Context, req *ExecuteToolRequest, opts ...entity.ExecuteToolOpt) (resp *ExecuteToolResponse, err error)
|
||||
|
||||
// Product
|
||||
ListPluginProducts(ctx context.Context, req *ListPluginProductsRequest) (resp *ListPluginProductsResponse, err error)
|
||||
GetPluginProductAllTools(ctx context.Context, pluginID int64) (tools []*entity.ToolInfo, err error)
|
||||
|
||||
GetOAuthStatus(ctx context.Context, userID, pluginID int64) (resp *GetOAuthStatusResponse, err error)
|
||||
GetAgentPluginsOAuthStatus(ctx context.Context, userID, agentID int64) (status []*AgentPluginOAuthStatus, err error)
|
||||
OAuthCode(ctx context.Context, code string, state *entity.OAuthState) (err error)
|
||||
GetAccessToken(ctx context.Context, oa *entity.OAuthInfo) (accessToken string, err error)
|
||||
RevokeAccessToken(ctx context.Context, meta *entity.AuthorizationCodeMeta) (err error)
|
||||
}
|
||||
|
||||
type CreateDraftPluginRequest struct {
|
||||
PluginType common.PluginType
|
||||
IconURI string
|
||||
SpaceID int64
|
||||
DeveloperID int64
|
||||
ProjectID *int64
|
||||
Name string
|
||||
Desc string
|
||||
ServerURL string
|
||||
CommonParams map[common.ParameterLocation][]*common.CommonParamSchema
|
||||
AuthInfo *PluginAuthInfo
|
||||
}
|
||||
|
||||
type UpdateDraftPluginWithCodeRequest struct {
|
||||
UserID int64
|
||||
PluginID int64
|
||||
OpenapiDoc *model.Openapi3T
|
||||
Manifest *entity.PluginManifest
|
||||
}
|
||||
|
||||
type UpdateDraftPluginRequest struct {
|
||||
PluginID int64
|
||||
Name *string
|
||||
Desc *string
|
||||
URL *string
|
||||
Icon *common.PluginIcon
|
||||
CommonParams map[common.ParameterLocation][]*common.CommonParamSchema
|
||||
AuthInfo *PluginAuthInfo
|
||||
}
|
||||
|
||||
type ListDraftPluginsRequest struct {
|
||||
SpaceID int64
|
||||
APPID int64
|
||||
PageInfo entity.PageInfo
|
||||
}
|
||||
|
||||
type ListDraftPluginsResponse struct {
|
||||
Plugins []*entity.PluginInfo
|
||||
Total int64
|
||||
}
|
||||
|
||||
type CreateDraftPluginWithCodeRequest struct {
|
||||
SpaceID int64
|
||||
DeveloperID int64
|
||||
ProjectID *int64
|
||||
Manifest *entity.PluginManifest
|
||||
OpenapiDoc *model.Openapi3T
|
||||
}
|
||||
|
||||
type CreateDraftPluginWithCodeResponse struct {
|
||||
Plugin *entity.PluginInfo
|
||||
Tools []*entity.ToolInfo
|
||||
}
|
||||
|
||||
type CreateDraftToolsWithCodeRequest struct {
|
||||
PluginID int64
|
||||
OpenapiDoc *model.Openapi3T
|
||||
|
||||
ConflictAndUpdate bool
|
||||
}
|
||||
|
||||
type CreateDraftToolsWithCodeResponse struct {
|
||||
DuplicatedTools []entity.UniqueToolAPI
|
||||
}
|
||||
|
||||
type PluginAuthInfo struct {
|
||||
AuthzType *model.AuthzType
|
||||
Location *model.HTTPParamLocation
|
||||
Key *string
|
||||
ServiceToken *string
|
||||
OAuthInfo *string
|
||||
AuthzSubType *model.AuthzSubType
|
||||
AuthzPayload *string
|
||||
}
|
||||
|
||||
func (p PluginAuthInfo) toAuthV2() (*model.AuthV2, error) {
|
||||
if p.AuthzType == nil {
|
||||
return nil, errorx.New(errno.ErrPluginInvalidManifest, errorx.KV(errno.PluginMsgKey, "auth type is required"))
|
||||
}
|
||||
|
||||
switch *p.AuthzType {
|
||||
case model.AuthzTypeOfNone:
|
||||
return &model.AuthV2{
|
||||
Type: model.AuthzTypeOfNone,
|
||||
}, nil
|
||||
|
||||
case model.AuthzTypeOfOAuth:
|
||||
m, err := p.authOfOAuthToAuthV2()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
|
||||
case model.AuthzTypeOfService:
|
||||
m, err := p.authOfServiceToAuthV2()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
|
||||
default:
|
||||
return nil, errorx.New(errno.ErrPluginInvalidManifest, errorx.KVf(errno.PluginMsgKey,
|
||||
"the type '%s' of auth is invalid", *p.AuthzType))
|
||||
}
|
||||
}
|
||||
|
||||
func (p PluginAuthInfo) authOfOAuthToAuthV2() (*model.AuthV2, error) {
|
||||
if p.AuthzSubType == nil {
|
||||
return nil, errorx.New(errno.ErrPluginInvalidManifest, errorx.KV(errno.PluginMsgKey, "sub-auth type is required"))
|
||||
}
|
||||
|
||||
if p.OAuthInfo == nil || *p.OAuthInfo == "" {
|
||||
return nil, errorx.New(errno.ErrPluginInvalidManifest, errorx.KV(errno.PluginMsgKey, "oauth info is required"))
|
||||
}
|
||||
|
||||
oauthInfo := make(map[string]string)
|
||||
err := sonic.Unmarshal([]byte(*p.OAuthInfo), &oauthInfo)
|
||||
if err != nil {
|
||||
return nil, errorx.WrapByCode(err, errno.ErrPluginInvalidManifest, errorx.KV(errno.PluginMsgKey, "invalid oauth info"))
|
||||
}
|
||||
|
||||
if *p.AuthzSubType == model.AuthzSubTypeOfOAuthClientCredentials {
|
||||
_oauthInfo := &model.OAuthClientCredentialsConfig{
|
||||
ClientID: oauthInfo["client_id"],
|
||||
ClientSecret: oauthInfo["client_secret"],
|
||||
TokenURL: oauthInfo["token_url"],
|
||||
}
|
||||
|
||||
str, err := sonic.MarshalString(_oauthInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal oauth info failed, err=%v", err)
|
||||
}
|
||||
|
||||
return &model.AuthV2{
|
||||
Type: model.AuthzTypeOfOAuth,
|
||||
SubType: model.AuthzSubTypeOfOAuthClientCredentials,
|
||||
Payload: str,
|
||||
AuthOfOAuthClientCredentials: _oauthInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if *p.AuthzSubType == model.AuthzSubTypeOfOAuthAuthorizationCode {
|
||||
contentType := oauthInfo["authorization_content_type"]
|
||||
if contentType != model.MediaTypeJson { // only support application/json
|
||||
return nil, errorx.New(errno.ErrPluginInvalidManifest, errorx.KVf(errno.PluginMsgKey,
|
||||
"the type '%s' of authorization content is invalid", contentType))
|
||||
}
|
||||
|
||||
_oauthInfo := &model.OAuthAuthorizationCodeConfig{
|
||||
ClientID: oauthInfo["client_id"],
|
||||
ClientSecret: oauthInfo["client_secret"],
|
||||
ClientURL: oauthInfo["client_url"],
|
||||
Scope: oauthInfo["scope"],
|
||||
AuthorizationURL: oauthInfo["authorization_url"],
|
||||
AuthorizationContentType: contentType,
|
||||
}
|
||||
|
||||
str, err := sonic.MarshalString(_oauthInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal oauth info failed, err=%v", err)
|
||||
}
|
||||
|
||||
return &model.AuthV2{
|
||||
Type: model.AuthzTypeOfOAuth,
|
||||
SubType: model.AuthzSubTypeOfOAuthAuthorizationCode,
|
||||
Payload: str,
|
||||
AuthOfOAuthAuthorizationCode: _oauthInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, errorx.New(errno.ErrPluginInvalidManifest, errorx.KVf(errno.PluginMsgKey,
|
||||
"the type '%s' of sub-auth is invalid", *p.AuthzSubType))
|
||||
}
|
||||
|
||||
func (p PluginAuthInfo) authOfServiceToAuthV2() (*model.AuthV2, error) {
|
||||
if p.AuthzSubType == nil {
|
||||
return nil, fmt.Errorf("sub-auth type is required")
|
||||
}
|
||||
|
||||
if *p.AuthzSubType == model.AuthzSubTypeOfServiceAPIToken {
|
||||
if p.Location == nil {
|
||||
return nil, fmt.Errorf("'Location' of sub-auth is required")
|
||||
}
|
||||
if p.ServiceToken == nil {
|
||||
return nil, fmt.Errorf("'ServiceToken' of sub-auth is required")
|
||||
}
|
||||
if p.Key == nil {
|
||||
return nil, fmt.Errorf("'Key' of sub-auth is required")
|
||||
}
|
||||
|
||||
tokenAuth := &model.AuthOfAPIToken{
|
||||
ServiceToken: *p.ServiceToken,
|
||||
Location: model.HTTPParamLocation(strings.ToLower(string(*p.Location))),
|
||||
Key: *p.Key,
|
||||
}
|
||||
|
||||
str, err := sonic.MarshalString(tokenAuth)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal token auth failed, err=%v", err)
|
||||
}
|
||||
|
||||
return &model.AuthV2{
|
||||
Type: model.AuthzTypeOfService,
|
||||
SubType: model.AuthzSubTypeOfServiceAPIToken,
|
||||
Payload: str,
|
||||
AuthOfAPIToken: tokenAuth,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, errorx.New(errno.ErrPluginInvalidManifest, errorx.KVf(errno.PluginMsgKey,
|
||||
"the type '%s' of sub-auth is invalid", *p.AuthzSubType))
|
||||
}
|
||||
|
||||
type PublishPluginRequest = model.PublishPluginRequest
|
||||
|
||||
type PublishAPPPluginsRequest = model.PublishAPPPluginsRequest
|
||||
|
||||
type PublishAPPPluginsResponse = model.PublishAPPPluginsResponse
|
||||
|
||||
type MGetPluginLatestVersionResponse = model.MGetPluginLatestVersionResponse
|
||||
|
||||
type UpdateToolDraftRequest struct {
|
||||
PluginID int64
|
||||
ToolID int64
|
||||
Name *string
|
||||
Desc *string
|
||||
SubURL *string
|
||||
Method *string
|
||||
Parameters openapi3.Parameters
|
||||
RequestBody *openapi3.RequestBodyRef
|
||||
Responses openapi3.Responses
|
||||
Disabled *bool
|
||||
SaveExample *bool
|
||||
DebugExample *common.DebugExample
|
||||
APIExtend *common.APIExtend
|
||||
}
|
||||
|
||||
type MGetAgentToolsRequest = model.MGetAgentToolsRequest
|
||||
|
||||
type UpdateBotDefaultParamsRequest struct {
|
||||
PluginID int64
|
||||
AgentID int64
|
||||
ToolName string
|
||||
Parameters openapi3.Parameters
|
||||
RequestBody *openapi3.RequestBodyRef
|
||||
Responses openapi3.Responses
|
||||
}
|
||||
|
||||
type ExecuteToolRequest = model.ExecuteToolRequest
|
||||
|
||||
type ExecuteToolResponse = model.ExecuteToolResponse
|
||||
|
||||
type ListPluginProductsRequest struct{}
|
||||
|
||||
type ListPluginProductsResponse struct {
|
||||
Plugins []*entity.PluginInfo
|
||||
Total int64
|
||||
}
|
||||
|
||||
type ConvertToOpenapi3DocRequest struct {
|
||||
RawInput string
|
||||
PluginServerURL *string
|
||||
}
|
||||
|
||||
type ConvertToOpenapi3DocResponse struct {
|
||||
OpenapiDoc *model.Openapi3T
|
||||
Manifest *entity.PluginManifest
|
||||
Format common.PluginDataFormat
|
||||
ErrMsg string
|
||||
}
|
||||
|
||||
type GetOAuthStatusResponse struct {
|
||||
IsOauth bool
|
||||
Status common.OAuthStatus
|
||||
OAuthURL string
|
||||
}
|
||||
|
||||
type AgentPluginOAuthStatus struct {
|
||||
PluginID int64
|
||||
PluginName string
|
||||
PluginIconURL string
|
||||
Status common.OAuthStatus
|
||||
}
|
||||
|
||||
type CopyPluginRequest struct {
|
||||
UserID int64
|
||||
PluginID int64
|
||||
CopyScene model.CopyScene
|
||||
|
||||
TargetAPPID *int64
|
||||
}
|
||||
|
||||
type CopyPluginResponse struct {
|
||||
Plugin *entity.PluginInfo
|
||||
Tools map[int64]*entity.ToolInfo // old tool id -> new tool
|
||||
}
|
||||
|
||||
type MoveAPPPluginToLibRequest struct {
|
||||
PluginID int64
|
||||
}
|
||||
|
||||
type GetAccessTokenRequest struct {
|
||||
UserID string
|
||||
PluginID *int64
|
||||
Mode model.AuthzSubType
|
||||
OAuthInfo *entity.OAuthInfo
|
||||
}
|
||||
Reference in New Issue
Block a user