feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
382
backend/domain/plugin/service/plugin_online.go
Normal file
382
backend/domain/plugin/service/plugin_online.go
Normal file
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* 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"
|
||||
"sort"
|
||||
|
||||
model "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/plugin"
|
||||
searchModel "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/search"
|
||||
pluginCommon "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop_common"
|
||||
resCommon "github.com/coze-dev/coze-studio/backend/api/model/resource/common"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crosssearch"
|
||||
pluginConf "github.com/coze-dev/coze-studio/backend/domain/plugin/conf"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/repository"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/slices"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/logs"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
func (p *pluginServiceImpl) GetOnlinePlugin(ctx context.Context, pluginID int64) (plugin *entity.PluginInfo, err error) {
|
||||
pl, exist, err := p.pluginRepo.GetOnlinePlugin(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "GetOnlinePlugin failed, pluginID=%d", pluginID)
|
||||
}
|
||||
if !exist {
|
||||
return nil, errorx.New(errno.ErrPluginRecordNotFound)
|
||||
}
|
||||
|
||||
return pl, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) MGetOnlinePlugins(ctx context.Context, pluginIDs []int64) (plugins []*entity.PluginInfo, err error) {
|
||||
plugins, err = p.pluginRepo.MGetOnlinePlugins(ctx, pluginIDs)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "MGetOnlinePlugins failed, pluginIDs=%v", pluginIDs)
|
||||
}
|
||||
|
||||
res := make([]*model.PluginInfo, 0, len(plugins))
|
||||
for _, pl := range plugins {
|
||||
res = append(res, pl.PluginInfo)
|
||||
}
|
||||
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) GetOnlineTool(ctx context.Context, toolID int64) (tool *entity.ToolInfo, err error) {
|
||||
tool, exist, err := p.toolRepo.GetOnlineTool(ctx, toolID)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "GetOnlineTool failed, toolID=%d", toolID)
|
||||
}
|
||||
if !exist {
|
||||
return nil, errorx.New(errno.ErrPluginRecordNotFound)
|
||||
}
|
||||
|
||||
return tool, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) MGetOnlineTools(ctx context.Context, toolIDs []int64) (tools []*entity.ToolInfo, err error) {
|
||||
tools, err = p.toolRepo.MGetOnlineTools(ctx, toolIDs)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "MGetOnlineTools failed, toolIDs=%v", toolIDs)
|
||||
}
|
||||
|
||||
return tools, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) MGetVersionTools(ctx context.Context, versionTools []entity.VersionTool) (tools []*entity.ToolInfo, err error) {
|
||||
tools, err = p.toolRepo.MGetVersionTools(ctx, versionTools)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "MGetVersionTools failed, versionTools=%v", versionTools)
|
||||
}
|
||||
|
||||
return tools, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) ListPluginProducts(ctx context.Context, req *ListPluginProductsRequest) (resp *ListPluginProductsResponse, err error) {
|
||||
plugins := slices.Transform(pluginConf.GetAllPluginProducts(), func(p *pluginConf.PluginInfo) *entity.PluginInfo {
|
||||
return entity.NewPluginInfo(p.Info)
|
||||
})
|
||||
sort.Slice(plugins, func(i, j int) bool {
|
||||
return plugins[i].GetRefProductID() < plugins[j].GetRefProductID()
|
||||
})
|
||||
|
||||
return &ListPluginProductsResponse{
|
||||
Plugins: plugins,
|
||||
Total: int64(len(plugins)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) GetPluginProductAllTools(ctx context.Context, pluginID int64) (tools []*entity.ToolInfo, err error) {
|
||||
res, err := p.toolRepo.GetPluginAllOnlineTools(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "GetPluginAllOnlineTools failed, pluginID=%d", pluginID)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) DeleteAPPAllPlugins(ctx context.Context, appID int64) (pluginIDs []int64, err error) {
|
||||
return p.pluginRepo.DeleteAPPAllPlugins(ctx, appID)
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) GetAPPAllPlugins(ctx context.Context, appID int64) (plugins []*entity.PluginInfo, err error) {
|
||||
plugins, err = p.pluginRepo.GetAPPAllDraftPlugins(ctx, appID)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "GetAPPAllDraftPlugins failed, appID=%d", appID)
|
||||
}
|
||||
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) MGetVersionPlugins(ctx context.Context, versionPlugins []entity.VersionPlugin) (plugins []*entity.PluginInfo, err error) {
|
||||
plugins, err = p.pluginRepo.MGetVersionPlugins(ctx, versionPlugins)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "MGetVersionPlugins failed, versionPlugins=%v", versionPlugins)
|
||||
}
|
||||
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) ListCustomOnlinePlugins(ctx context.Context, spaceID int64, pageInfo entity.PageInfo) (plugins []*entity.PluginInfo, total int64, err error) {
|
||||
if pageInfo.Name == nil || *pageInfo.Name == "" {
|
||||
plugins, total, err = p.pluginRepo.ListCustomOnlinePlugins(ctx, spaceID, pageInfo)
|
||||
if err != nil {
|
||||
return nil, 0, errorx.Wrapf(err, "ListCustomOnlinePlugins failed, spaceID=%d", spaceID)
|
||||
}
|
||||
return plugins, total, nil
|
||||
}
|
||||
|
||||
res, err := crosssearch.DefaultSVC().SearchResources(ctx, &searchModel.SearchResourcesRequest{
|
||||
SpaceID: spaceID,
|
||||
Name: *pageInfo.Name,
|
||||
OrderAsc: false,
|
||||
ResTypeFilter: []resCommon.ResType{
|
||||
resCommon.ResType_Plugin,
|
||||
},
|
||||
OrderFiledName: func() string {
|
||||
if pageInfo.SortBy == nil || *pageInfo.SortBy != entity.SortByCreatedAt {
|
||||
return searchModel.FieldOfUpdateTime
|
||||
}
|
||||
return searchModel.FieldOfCreateTime
|
||||
}(),
|
||||
Page: ptr.Of(int32(pageInfo.Page)),
|
||||
Limit: int32(pageInfo.Size),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, 0, errorx.Wrapf(err, "SearchResources failed, spaceID=%d", spaceID)
|
||||
}
|
||||
|
||||
plugins = make([]*entity.PluginInfo, 0, len(res.Data))
|
||||
for _, pl := range res.Data {
|
||||
draftPlugin, exist, err := p.pluginRepo.GetOnlinePlugin(ctx, pl.ResID)
|
||||
if err != nil {
|
||||
return nil, 0, errorx.Wrapf(err, "GetOnlinePlugin failed, pluginID=%d", pl.ResID)
|
||||
}
|
||||
if !exist {
|
||||
logs.CtxWarnf(ctx, "online plugin not exist, pluginID=%d", pl.ResID)
|
||||
continue
|
||||
}
|
||||
plugins = append(plugins, draftPlugin)
|
||||
}
|
||||
|
||||
if res.TotalHits != nil {
|
||||
total = *res.TotalHits
|
||||
}
|
||||
|
||||
return plugins, total, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) MGetPluginLatestVersion(ctx context.Context, pluginIDs []int64) (resp *MGetPluginLatestVersionResponse, err error) {
|
||||
plugins, err := p.pluginRepo.MGetOnlinePlugins(ctx, pluginIDs,
|
||||
repository.WithPluginID(),
|
||||
repository.WithPluginVersion())
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "MGetOnlinePlugins failed, pluginIDs=%v", pluginIDs)
|
||||
}
|
||||
|
||||
versions := make(map[int64]string, len(plugins))
|
||||
for _, pl := range plugins {
|
||||
versions[pl.ID] = pl.GetVersion()
|
||||
}
|
||||
|
||||
resp = &MGetPluginLatestVersionResponse{
|
||||
Versions: versions,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) CopyPlugin(ctx context.Context, req *CopyPluginRequest) (resp *CopyPluginResponse, err error) {
|
||||
err = p.checkCanCopyPlugin(ctx, req.PluginID, req.CopyScene)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
plugin, tools, err := p.getCopySourcePluginAndTools(ctx, req.PluginID, req.CopyScene)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.changePluginAndToolsInfoForCopy(req, plugin, tools)
|
||||
|
||||
toolMap := make(map[int64]*entity.ToolInfo, len(tools))
|
||||
for _, tool := range tools {
|
||||
toolMap[tool.ID] = tool
|
||||
}
|
||||
|
||||
plugin, tools, err = p.pluginRepo.CopyPlugin(ctx, &repository.CopyPluginRequest{
|
||||
Plugin: plugin,
|
||||
Tools: tools,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "CopyPlugin failed, pluginID=%d", req.PluginID)
|
||||
}
|
||||
|
||||
resp = &CopyPluginResponse{
|
||||
Plugin: plugin,
|
||||
Tools: toolMap,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) changePluginAndToolsInfoForCopy(req *CopyPluginRequest, plugin *entity.PluginInfo, tools []*entity.ToolInfo) {
|
||||
plugin.Version = nil
|
||||
plugin.VersionDesc = nil
|
||||
|
||||
plugin.DeveloperID = req.UserID
|
||||
|
||||
if req.CopyScene != model.CopySceneOfAPPDuplicate {
|
||||
plugin.SetName(fmt.Sprintf("%s_copy", plugin.GetName()))
|
||||
}
|
||||
|
||||
if req.CopyScene == model.CopySceneOfToLibrary {
|
||||
const (
|
||||
defaultVersion = "v0.0.1"
|
||||
defaultVersionDesc = "copy to library"
|
||||
)
|
||||
|
||||
plugin.APPID = nil
|
||||
plugin.Version = ptr.Of(defaultVersion)
|
||||
plugin.VersionDesc = ptr.Of(defaultVersionDesc)
|
||||
|
||||
for _, tool := range tools {
|
||||
tool.Version = ptr.Of(defaultVersion)
|
||||
}
|
||||
}
|
||||
|
||||
if req.CopyScene == model.CopySceneOfToAPP {
|
||||
plugin.APPID = req.TargetAPPID
|
||||
|
||||
for _, tool := range tools {
|
||||
tool.DebugStatus = ptr.Of(pluginCommon.APIDebugStatus_DebugPassed)
|
||||
}
|
||||
}
|
||||
|
||||
if req.CopyScene == model.CopySceneOfAPPDuplicate {
|
||||
plugin.APPID = req.TargetAPPID
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) checkCanCopyPlugin(ctx context.Context, pluginID int64, scene model.CopyScene) (err error) {
|
||||
switch scene {
|
||||
case model.CopySceneOfToAPP, model.CopySceneOfDuplicate, model.CopySceneOfAPPDuplicate:
|
||||
return nil
|
||||
case model.CopySceneOfToLibrary:
|
||||
return p.checkToolsDebugStatus(ctx, pluginID)
|
||||
default:
|
||||
return fmt.Errorf("unsupported copy scene '%s'", scene)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) getCopySourcePluginAndTools(ctx context.Context, pluginID int64, scene model.CopyScene) (plugin *entity.PluginInfo, tools []*entity.ToolInfo, err error) {
|
||||
switch scene {
|
||||
case model.CopySceneOfToAPP:
|
||||
return p.getOnlinePluginAndTools(ctx, pluginID)
|
||||
case model.CopySceneOfToLibrary, model.CopySceneOfDuplicate, model.CopySceneOfAPPDuplicate:
|
||||
return p.getDraftPluginAndTools(ctx, pluginID)
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("unsupported copy scene '%s'", scene)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) getOnlinePluginAndTools(ctx context.Context, pluginID int64) (plugin *entity.PluginInfo, tools []*entity.ToolInfo, err error) {
|
||||
onlinePlugin, exist, err := p.pluginRepo.GetOnlinePlugin(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !exist {
|
||||
return nil, nil, errorx.New(errno.ErrPluginRecordNotFound)
|
||||
}
|
||||
|
||||
onlineTools, err := p.toolRepo.GetPluginAllOnlineTools(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return onlinePlugin, onlineTools, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) getDraftPluginAndTools(ctx context.Context, pluginID int64) (plugin *entity.PluginInfo, tools []*entity.ToolInfo, err error) {
|
||||
draftPlugin, exist, err := p.pluginRepo.GetDraftPlugin(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !exist {
|
||||
return nil, nil, errorx.New(errno.ErrPluginRecordNotFound)
|
||||
}
|
||||
|
||||
draftTools, err := p.toolRepo.GetPluginAllDraftTools(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return draftPlugin, draftTools, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) MoveAPPPluginToLibrary(ctx context.Context, pluginID int64) (draftPlugin *entity.PluginInfo, err error) {
|
||||
draftPlugin, exist, err := p.pluginRepo.GetDraftPlugin(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exist {
|
||||
return nil, errorx.New(errno.ErrPluginRecordNotFound)
|
||||
}
|
||||
|
||||
err = p.checkToolsDebugStatus(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
draftTools, err := p.toolRepo.GetPluginAllDraftTools(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.changePluginAndToolsInfoForMove(draftPlugin, draftTools)
|
||||
|
||||
err = p.pluginRepo.MoveAPPPluginToLibrary(ctx, draftPlugin, draftTools)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "MoveAPPPluginToLibrary failed, pluginID=%d", pluginID)
|
||||
}
|
||||
|
||||
return draftPlugin, nil
|
||||
}
|
||||
|
||||
func (p *pluginServiceImpl) changePluginAndToolsInfoForMove(plugin *entity.PluginInfo,
|
||||
tools []*entity.ToolInfo) {
|
||||
|
||||
const (
|
||||
defaultVersion = "v0.0.1"
|
||||
defaultVersionDesc = "move to library"
|
||||
)
|
||||
|
||||
plugin.Version = ptr.Of(defaultVersion)
|
||||
plugin.VersionDesc = ptr.Of(defaultVersionDesc)
|
||||
|
||||
for _, tool := range tools {
|
||||
tool.Version = ptr.Of(defaultVersion)
|
||||
}
|
||||
|
||||
plugin.APPID = nil
|
||||
}
|
||||
Reference in New Issue
Block a user