You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
769 lines
23 KiB
769 lines
23 KiB
/*
|
|
* 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 singleagent
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
shortcutCmd "github.com/coze-dev/coze-studio/backend/domain/shortcutcmd/service"
|
|
"github.com/coze-dev/coze-studio/backend/pkg/lang/slices"
|
|
"github.com/coze-dev/coze-studio/backend/types/consts"
|
|
|
|
"github.com/bytedance/sonic"
|
|
"github.com/getkin/kin-openapi/openapi3"
|
|
|
|
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
|
|
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_open_api"
|
|
"github.com/coze-dev/coze-studio/backend/api/model/app/developer_api"
|
|
intelligence "github.com/coze-dev/coze-studio/backend/api/model/app/intelligence/common"
|
|
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/database"
|
|
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/plugin"
|
|
"github.com/coze-dev/coze-studio/backend/api/model/data/database/table"
|
|
"github.com/coze-dev/coze-studio/backend/api/model/playground"
|
|
"github.com/coze-dev/coze-studio/backend/application/base/ctxutil"
|
|
crossdatabase "github.com/coze-dev/coze-studio/backend/crossdomain/contract/database"
|
|
"github.com/coze-dev/coze-studio/backend/domain/agent/singleagent/entity"
|
|
singleagent "github.com/coze-dev/coze-studio/backend/domain/agent/singleagent/service"
|
|
variableEntity "github.com/coze-dev/coze-studio/backend/domain/memory/variables/entity"
|
|
shortcutEntity "github.com/coze-dev/coze-studio/backend/domain/shortcutcmd/entity"
|
|
|
|
searchEntity "github.com/coze-dev/coze-studio/backend/domain/search/entity"
|
|
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
|
"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/errno"
|
|
)
|
|
|
|
type SingleAgentApplicationService struct {
|
|
appContext *ServiceComponents
|
|
DomainSVC singleagent.SingleAgent
|
|
ShortcutCMDSVC shortcutCmd.ShortcutCmd
|
|
}
|
|
|
|
func newApplicationService(s *ServiceComponents, domain singleagent.SingleAgent) *SingleAgentApplicationService {
|
|
return &SingleAgentApplicationService{
|
|
appContext: s,
|
|
DomainSVC: domain,
|
|
ShortcutCMDSVC: s.ShortcutCMDDomainSVC,
|
|
}
|
|
}
|
|
|
|
const onboardingInfoMaxLength = 65535
|
|
|
|
func (s *SingleAgentApplicationService) generateOnboardingStr(onboardingInfo *bot_common.OnboardingInfo) (string, error) {
|
|
onboarding := playground.OnboardingContent{}
|
|
if onboardingInfo != nil {
|
|
onboarding.Prologue = ptr.Of(onboardingInfo.GetPrologue())
|
|
onboarding.SuggestedQuestions = onboardingInfo.GetSuggestedQuestions()
|
|
onboarding.SuggestedQuestionsShowMode = onboardingInfo.SuggestedQuestionsShowMode
|
|
}
|
|
|
|
onboardingInfoStr, err := sonic.MarshalString(onboarding)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return onboardingInfoStr, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) UpdateSingleAgentDraft(ctx context.Context, req *playground.UpdateDraftBotInfoAgwRequest) (*playground.UpdateDraftBotInfoAgwResponse, error) {
|
|
if req.BotInfo.OnboardingInfo != nil {
|
|
infoStr, err := s.generateOnboardingStr(req.BotInfo.OnboardingInfo)
|
|
if err != nil {
|
|
return nil, errorx.New(errno.ErrAgentPermissionCode, errorx.KV("msg", "onboarding_info invalidate"))
|
|
}
|
|
|
|
if len(infoStr) > onboardingInfoMaxLength {
|
|
return nil, errorx.New(errno.ErrAgentPermissionCode, errorx.KV("msg", "onboarding_info is too long"))
|
|
}
|
|
}
|
|
|
|
agentID := req.BotInfo.GetBotId()
|
|
currentAgentInfo, err := s.ValidateAgentDraftAccess(ctx, agentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
userID := ctxutil.MustGetUIDFromCtx(ctx)
|
|
|
|
updateAgentInfo, err := s.applyAgentUpdates(currentAgentInfo, req.BotInfo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if req.BotInfo.VariableList != nil {
|
|
var (
|
|
varsMetaID int64
|
|
vars = variableEntity.NewVariablesWithAgentVariables(req.BotInfo.VariableList)
|
|
)
|
|
|
|
varsMetaID, err = s.appContext.VariablesDomainSVC.UpsertBotMeta(ctx, agentID, "", userID, vars)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
updateAgentInfo.VariablesMetaID = &varsMetaID
|
|
}
|
|
|
|
err = s.DomainSVC.UpdateSingleAgentDraft(ctx, updateAgentInfo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = s.appContext.EventBus.PublishProject(ctx, &searchEntity.ProjectDomainEvent{
|
|
OpType: searchEntity.Updated,
|
|
Project: &searchEntity.ProjectDocument{
|
|
ID: agentID,
|
|
Name: &updateAgentInfo.Name,
|
|
Type: intelligence.IntelligenceType_Bot,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &playground.UpdateDraftBotInfoAgwResponse{
|
|
Data: &playground.UpdateDraftBotInfoAgwData{
|
|
HasChange: ptr.Of(true),
|
|
CheckNotPass: false,
|
|
Branch: playground.BranchPtr(playground.Branch_PersonalDraft),
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) UpdatePromptDisable(ctx context.Context, req *table.UpdateDatabaseBotSwitchRequest) (*table.UpdateDatabaseBotSwitchResponse, error) {
|
|
agentID := req.GetBotID()
|
|
draft, err := s.ValidateAgentDraftAccess(ctx, agentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(draft.Database) == 0 {
|
|
return nil, fmt.Errorf("agent %d has no database", agentID) // TODO (@fanlv): error code
|
|
}
|
|
|
|
dbInfos := draft.Database
|
|
var found bool
|
|
for _, db := range dbInfos {
|
|
if db.GetTableId() == conv.Int64ToStr(req.GetDatabaseID()) {
|
|
db.PromptDisabled = ptr.Of(req.GetPromptDisable())
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
return nil, fmt.Errorf("database %d not found in agent %d", req.GetDatabaseID(), agentID) // TODO (@fanlv): error code
|
|
}
|
|
|
|
draft.Database = dbInfos
|
|
err = s.DomainSVC.UpdateSingleAgentDraft(ctx, draft)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &table.UpdateDatabaseBotSwitchResponse{
|
|
Code: 0,
|
|
Msg: "success",
|
|
}, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) UnBindDatabase(ctx context.Context, req *table.BindDatabaseToBotRequest) (*table.BindDatabaseToBotResponse, error) {
|
|
agentID := req.GetBotID()
|
|
draft, err := s.ValidateAgentDraftAccess(ctx, agentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(draft.Database) == 0 {
|
|
return nil, fmt.Errorf("agent %d has no database", agentID)
|
|
}
|
|
|
|
dbInfos := draft.Database
|
|
var found bool
|
|
newDBInfos := make([]*bot_common.Database, 0)
|
|
for _, db := range dbInfos {
|
|
if db.GetTableId() == conv.Int64ToStr(req.GetDatabaseID()) {
|
|
found = true
|
|
continue
|
|
}
|
|
newDBInfos = append(newDBInfos, db)
|
|
}
|
|
|
|
if !found {
|
|
return nil, fmt.Errorf("database %d not found in agent %d", req.GetDatabaseID(), agentID)
|
|
}
|
|
|
|
draft.Database = newDBInfos
|
|
err = s.DomainSVC.UpdateSingleAgentDraft(ctx, draft)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = crossdatabase.DefaultSVC().UnBindDatabase(ctx, &database.UnBindDatabaseToAgentRequest{
|
|
AgentID: agentID,
|
|
DraftDatabaseID: req.GetDatabaseID(),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &table.BindDatabaseToBotResponse{
|
|
Code: 0,
|
|
Msg: "success",
|
|
}, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) BindDatabase(ctx context.Context, req *table.BindDatabaseToBotRequest) (*table.BindDatabaseToBotResponse, error) {
|
|
agentID := req.GetBotID()
|
|
draft, err := s.ValidateAgentDraftAccess(ctx, agentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dbMap := slices.ToMap(draft.Database, func(d *bot_common.Database) (string, *bot_common.Database) {
|
|
return d.GetTableId(), d
|
|
})
|
|
if _, ok := dbMap[conv.Int64ToStr(req.GetDatabaseID())]; ok {
|
|
return nil, errorx.New(errno.ErrAgentPermissionCode, errorx.KVf("msg", "database %d already bound to agent %d", req.GetDatabaseID(), agentID))
|
|
}
|
|
|
|
basics := []*database.DatabaseBasic{
|
|
{
|
|
ID: req.DatabaseID,
|
|
TableType: table.TableType_DraftTable,
|
|
},
|
|
}
|
|
|
|
draftRes, err := crossdatabase.DefaultSVC().MGetDatabase(ctx, &database.MGetDatabaseRequest{
|
|
Basics: basics,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(draftRes.Databases) == 0 {
|
|
return nil, fmt.Errorf("database %d not found", req.DatabaseID)
|
|
}
|
|
|
|
draftDatabase := draftRes.Databases[0]
|
|
|
|
fields := make([]*bot_common.FieldItem, 0, len(draftDatabase.FieldList))
|
|
for _, field := range draftDatabase.FieldList {
|
|
fields = append(fields, &bot_common.FieldItem{
|
|
Name: ptr.Of(field.Name),
|
|
Desc: ptr.Of(field.Desc),
|
|
Type: ptr.Of(bot_common.FieldItemType(field.Type)),
|
|
MustRequired: ptr.Of(field.MustRequired),
|
|
AlterId: ptr.Of(field.AlterID),
|
|
Id: ptr.Of(int64(0)),
|
|
})
|
|
}
|
|
|
|
bindDB := &bot_common.Database{
|
|
TableId: ptr.Of(strconv.FormatInt(draftDatabase.ID, 10)),
|
|
TableName: ptr.Of(draftDatabase.TableName),
|
|
TableDesc: ptr.Of(draftDatabase.TableDesc),
|
|
FieldList: fields,
|
|
RWMode: ptr.Of(bot_common.BotTableRWMode(draftDatabase.RwMode)),
|
|
}
|
|
|
|
if len(draft.Database) == 0 {
|
|
draft.Database = make([]*bot_common.Database, 0, 1)
|
|
}
|
|
draft.Database = append(draft.Database, bindDB)
|
|
|
|
err = s.DomainSVC.UpdateSingleAgentDraft(ctx, draft)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = crossdatabase.DefaultSVC().BindDatabase(ctx, &database.BindDatabaseToAgentRequest{
|
|
AgentID: agentID,
|
|
DraftDatabaseID: req.GetDatabaseID(),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &table.BindDatabaseToBotResponse{
|
|
Code: 0,
|
|
Msg: "success",
|
|
}, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) applyAgentUpdates(target *entity.SingleAgent, patch *bot_common.BotInfoForUpdate) (*entity.SingleAgent, error) {
|
|
if patch.Name != nil {
|
|
target.Name = *patch.Name
|
|
}
|
|
|
|
if patch.Description != nil {
|
|
target.Desc = *patch.Description
|
|
}
|
|
|
|
if patch.IconUri != nil {
|
|
target.IconURI = *patch.IconUri
|
|
}
|
|
|
|
if patch.OnboardingInfo != nil {
|
|
target.OnboardingInfo = patch.OnboardingInfo
|
|
}
|
|
|
|
if patch.ModelInfo != nil {
|
|
target.ModelInfo = patch.ModelInfo
|
|
}
|
|
|
|
if patch.PromptInfo != nil {
|
|
target.Prompt = patch.PromptInfo
|
|
}
|
|
|
|
if patch.WorkflowInfoList != nil {
|
|
target.Workflow = patch.WorkflowInfoList
|
|
}
|
|
|
|
if patch.PluginInfoList != nil {
|
|
target.Plugin = patch.PluginInfoList
|
|
}
|
|
|
|
if patch.Knowledge != nil {
|
|
target.Knowledge = patch.Knowledge
|
|
}
|
|
|
|
if patch.SuggestReplyInfo != nil {
|
|
target.SuggestReply = patch.SuggestReplyInfo
|
|
}
|
|
|
|
if patch.BackgroundImageInfoList != nil {
|
|
target.BackgroundImageInfoList = patch.BackgroundImageInfoList
|
|
}
|
|
|
|
if patch.Agents != nil && len(patch.Agents) > 0 && patch.Agents[0].JumpConfig != nil {
|
|
target.JumpConfig = patch.Agents[0].JumpConfig
|
|
}
|
|
|
|
if patch.ShortcutSort != nil {
|
|
target.ShortcutCommand = patch.ShortcutSort
|
|
}
|
|
|
|
if patch.DatabaseList != nil {
|
|
for _, db := range patch.DatabaseList {
|
|
if db.PromptDisabled == nil {
|
|
db.PromptDisabled = ptr.Of(false) // default is false
|
|
}
|
|
}
|
|
target.Database = patch.DatabaseList
|
|
}
|
|
if patch.BotMode != nil {
|
|
target.BotMode = ptr.From(patch.BotMode)
|
|
}
|
|
if patch.LayoutInfo != nil {
|
|
target.LayoutInfo = patch.LayoutInfo
|
|
}
|
|
|
|
return target, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) DeleteAgentDraft(ctx context.Context, req *developer_api.DeleteDraftBotRequest) (*developer_api.DeleteDraftBotResponse, error) {
|
|
_, err := s.ValidateAgentDraftAccess(ctx, req.GetBotID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = s.DomainSVC.DeleteAgentDraft(ctx, req.GetSpaceID(), req.GetBotID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = s.appContext.EventBus.PublishProject(ctx, &searchEntity.ProjectDomainEvent{
|
|
OpType: searchEntity.Deleted,
|
|
Project: &searchEntity.ProjectDocument{
|
|
ID: req.GetBotID(),
|
|
Type: intelligence.IntelligenceType_Bot,
|
|
},
|
|
})
|
|
if err != nil {
|
|
logs.CtxWarnf(ctx, "publish delete project event failed id = %v , err = %v", req.GetBotID(), err)
|
|
}
|
|
|
|
return &developer_api.DeleteDraftBotResponse{
|
|
Data: &developer_api.DeleteDraftBotData{},
|
|
Code: 0,
|
|
}, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) singleAgentDraftDo2Vo(ctx context.Context, do *entity.SingleAgent) (*bot_common.BotInfo, error) {
|
|
vo := &bot_common.BotInfo{
|
|
BotId: do.AgentID,
|
|
Name: do.Name,
|
|
Description: do.Desc,
|
|
IconUri: do.IconURI,
|
|
OnboardingInfo: do.OnboardingInfo,
|
|
ModelInfo: do.ModelInfo,
|
|
PromptInfo: do.Prompt,
|
|
PluginInfoList: do.Plugin,
|
|
Knowledge: do.Knowledge,
|
|
WorkflowInfoList: do.Workflow,
|
|
SuggestReplyInfo: do.SuggestReply,
|
|
CreatorId: do.CreatorID,
|
|
TaskInfo: &bot_common.TaskInfo{},
|
|
CreateTime: do.CreatedAt / 1000,
|
|
UpdateTime: do.UpdatedAt / 1000,
|
|
BotMode: do.BotMode,
|
|
BackgroundImageInfoList: do.BackgroundImageInfoList,
|
|
Status: bot_common.BotStatus_Using,
|
|
DatabaseList: do.Database,
|
|
ShortcutSort: do.ShortcutCommand,
|
|
LayoutInfo: do.LayoutInfo,
|
|
}
|
|
|
|
if do.VariablesMetaID != nil {
|
|
vars, err := s.appContext.VariablesDomainSVC.GetVariableMetaByID(ctx, *do.VariablesMetaID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if vars != nil {
|
|
vo.VariableList = vars.ToAgentVariables()
|
|
}
|
|
}
|
|
|
|
if vo.IconUri != "" {
|
|
url, err := s.appContext.TosClient.GetObjectUrl(ctx, vo.IconUri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
vo.IconUrl = url
|
|
}
|
|
|
|
if vo.ModelInfo == nil || vo.ModelInfo.ModelId == nil {
|
|
mi, err := s.defaultModelInfo(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
vo.ModelInfo = mi
|
|
}
|
|
|
|
return vo, nil
|
|
}
|
|
|
|
func disabledParam(schemaVal *openapi3.Schema) bool {
|
|
if len(schemaVal.Extensions) == 0 {
|
|
return false
|
|
}
|
|
globalDisable, localDisable := false, false
|
|
if v, ok := schemaVal.Extensions[plugin.APISchemaExtendLocalDisable]; ok {
|
|
localDisable = v.(bool)
|
|
}
|
|
if v, ok := schemaVal.Extensions[plugin.APISchemaExtendGlobalDisable]; ok {
|
|
globalDisable = v.(bool)
|
|
}
|
|
return globalDisable || localDisable
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) UpdateAgentDraftDisplayInfo(ctx context.Context, req *developer_api.UpdateDraftBotDisplayInfoRequest) (*developer_api.UpdateDraftBotDisplayInfoResponse, error) {
|
|
uid := ctxutil.GetUIDFromCtx(ctx)
|
|
if uid == nil {
|
|
return nil, errorx.New(errno.ErrAgentPermissionCode, errorx.KV("msg", "session required"))
|
|
}
|
|
|
|
_, err := s.ValidateAgentDraftAccess(ctx, req.BotID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
draftInfoDo := &entity.AgentDraftDisplayInfo{
|
|
AgentID: req.BotID,
|
|
DisplayInfo: req.DisplayInfo,
|
|
SpaceID: req.SpaceID,
|
|
}
|
|
|
|
err = s.DomainSVC.UpdateAgentDraftDisplayInfo(ctx, *uid, draftInfoDo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &developer_api.UpdateDraftBotDisplayInfoResponse{
|
|
Code: 0,
|
|
Msg: "success",
|
|
}, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) GetAgentDraftDisplayInfo(ctx context.Context, req *developer_api.GetDraftBotDisplayInfoRequest) (*developer_api.GetDraftBotDisplayInfoResponse, error) {
|
|
uid := ctxutil.GetUIDFromCtx(ctx)
|
|
if uid == nil {
|
|
return nil, errorx.New(errno.ErrAgentPermissionCode, errorx.KV("msg", "session required"))
|
|
}
|
|
|
|
_, err := s.ValidateAgentDraftAccess(ctx, req.BotID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
draftInfoDo, err := s.DomainSVC.GetAgentDraftDisplayInfo(ctx, *uid, req.BotID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &developer_api.GetDraftBotDisplayInfoResponse{
|
|
Code: 0,
|
|
Msg: "success",
|
|
Data: draftInfoDo.DisplayInfo,
|
|
}, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) ValidateAgentDraftAccess(ctx context.Context, agentID int64) (*entity.SingleAgent, error) {
|
|
uid := ctxutil.GetUIDFromCtx(ctx)
|
|
if uid == nil {
|
|
return nil, errorx.New(errno.ErrAgentPermissionCode, errorx.KV("msg", "session uid not found"))
|
|
}
|
|
|
|
do, err := s.DomainSVC.GetSingleAgentDraft(ctx, agentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if do == nil {
|
|
return nil, errorx.New(errno.ErrAgentPermissionCode, errorx.KVf("msg", "No agent draft(%d) found for the given agent ID", agentID))
|
|
}
|
|
|
|
if do.SpaceID == consts.TemplateSpaceID { // duplicate template, not need check uid permission
|
|
return do, nil
|
|
}
|
|
|
|
if do.CreatorID != *uid {
|
|
logs.CtxErrorf(ctx, "user(%d) is not the creator(%d) of the agent draft", *uid, do.CreatorID)
|
|
|
|
return do, errorx.New(errno.ErrAgentPermissionCode, errorx.KV("detail", "you are not the agent owner"))
|
|
}
|
|
|
|
return do, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) ListAgentPublishHistory(ctx context.Context, req *developer_api.ListDraftBotHistoryRequest) (*developer_api.ListDraftBotHistoryResponse, error) {
|
|
resp := &developer_api.ListDraftBotHistoryResponse{}
|
|
draftAgent, err := s.ValidateAgentDraftAccess(ctx, req.BotID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var connectorID *int64
|
|
if req.GetConnectorID() != "" {
|
|
var id int64
|
|
id, err = conv.StrToInt64(req.GetConnectorID())
|
|
if err != nil {
|
|
return nil, errorx.New(errno.ErrAgentInvalidParamCode, errorx.KV("msg", fmt.Sprintf("ConnectorID %v invalidate", *req.ConnectorID)))
|
|
}
|
|
|
|
connectorID = ptr.Of(id)
|
|
}
|
|
|
|
historyList, err := s.DomainSVC.ListAgentPublishHistory(ctx, draftAgent.AgentID, req.PageIndex, req.PageSize, connectorID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
uid := ctxutil.MustGetUIDFromCtx(ctx)
|
|
resp.Data = &developer_api.ListDraftBotHistoryData{}
|
|
|
|
for _, v := range historyList {
|
|
connectorInfos := make([]*developer_api.ConnectorInfo, 0, len(v.ConnectorIds))
|
|
infos, err := s.appContext.ConnectorDomainSVC.GetByIDs(ctx, v.ConnectorIds)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, info := range infos {
|
|
connectorInfos = append(connectorInfos, info.ToVO())
|
|
}
|
|
|
|
creator, err := s.appContext.UserDomainSVC.GetUserProfiles(ctx, v.CreatorID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
info := ""
|
|
if v.PublishInfo != nil {
|
|
info = *v.PublishInfo
|
|
}
|
|
|
|
historyInfo := &developer_api.HistoryInfo{
|
|
HistoryType: developer_api.HistoryType_FLAG,
|
|
Version: v.Version,
|
|
Info: info,
|
|
CreateTime: conv.Int64ToStr(v.CreatedAt / 1000),
|
|
ConnectorInfos: connectorInfos,
|
|
Creator: &developer_api.Creator{
|
|
ID: v.CreatorID,
|
|
Name: creator.Name,
|
|
AvatarURL: creator.IconURL,
|
|
Self: uid == v.CreatorID,
|
|
// UserUniqueName: creator. UserUniqueName,//TODO (@fanlv): Change the user domain after it is completed
|
|
// UserLabel TODO
|
|
},
|
|
PublishID: &v.PublishID,
|
|
}
|
|
|
|
resp.Data.HistoryInfos = append(resp.Data.HistoryInfos, historyInfo)
|
|
}
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) ReportUserBehavior(ctx context.Context, req *playground.ReportUserBehaviorRequest) (resp *playground.ReportUserBehaviorResponse, err error) {
|
|
err = s.appContext.EventBus.PublishProject(ctx, &searchEntity.ProjectDomainEvent{
|
|
OpType: searchEntity.Updated,
|
|
Project: &searchEntity.ProjectDocument{
|
|
ID: req.ResourceID,
|
|
SpaceID: req.SpaceID,
|
|
Type: intelligence.IntelligenceType_Bot,
|
|
IsRecentlyOpen: ptr.Of(1),
|
|
RecentlyOpenMS: ptr.Of(time.Now().UnixMilli()),
|
|
},
|
|
})
|
|
if err != nil {
|
|
logs.CtxWarnf(ctx, "publish updated project event failed id=%v, err=%v", req.ResourceID, err)
|
|
}
|
|
|
|
return &playground.ReportUserBehaviorResponse{}, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) GetAgentOnlineInfo(ctx context.Context, req *bot_open_api.GetBotOnlineInfoReq) (*bot_common.OpenAPIBotInfo, error) {
|
|
|
|
uid := ctxutil.MustGetUIDFromApiAuthCtx(ctx)
|
|
|
|
connectorID, err := conv.StrToInt64(ptr.From(req.ConnectorID))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if connectorID == 0 {
|
|
connectorID = ctxutil.GetApiAuthFromCtx(ctx).ConnectorID
|
|
}
|
|
|
|
return s.getAgentInfo(ctx, req.BotID, connectorID, uid, req.Version)
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) getAgentInfo(ctx context.Context, botID int64, connectorID int64, uid int64, version *string) (*bot_common.OpenAPIBotInfo, error) {
|
|
ae := &entity.AgentIdentity{
|
|
AgentID: botID,
|
|
ConnectorID: connectorID,
|
|
}
|
|
if version != nil {
|
|
ae.Version = ptr.From(version)
|
|
}
|
|
agentInfo, err := s.DomainSVC.ObtainAgentByIdentity(ctx, ae)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if agentInfo == nil {
|
|
logs.CtxErrorf(ctx, "agent(%d) is not exist", botID)
|
|
return nil, errorx.New(errno.ErrAgentPermissionCode, errorx.KV("msg", "agent not exist"))
|
|
}
|
|
if agentInfo.CreatorID != uid {
|
|
return nil, errorx.New(errno.ErrPromptPermissionCode, errorx.KV("msg", "agent not own"))
|
|
}
|
|
combineInfo := &bot_common.OpenAPIBotInfo{
|
|
BotID: agentInfo.AgentID,
|
|
Name: agentInfo.Name,
|
|
Description: agentInfo.Desc,
|
|
IconURL: agentInfo.IconURI,
|
|
Version: agentInfo.Version,
|
|
BotMode: bot_common.BotMode_SingleMode,
|
|
PromptInfo: agentInfo.Prompt,
|
|
OnboardingInfo: agentInfo.OnboardingInfo,
|
|
ModelInfo: agentInfo.ModelInfo,
|
|
WorkflowInfoList: agentInfo.Workflow,
|
|
PluginInfoList: agentInfo.Plugin,
|
|
}
|
|
|
|
if agentInfo.IconURI != "" {
|
|
url, err := s.appContext.TosClient.GetObjectUrl(ctx, agentInfo.IconURI)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
combineInfo.IconURL = url
|
|
}
|
|
|
|
if len(agentInfo.ShortcutCommand) > 0 {
|
|
shortcutInfos, err := s.ShortcutCMDSVC.ListCMD(ctx, &shortcutEntity.ListMeta{
|
|
ObjectID: agentInfo.AgentID,
|
|
IsOnline: 1,
|
|
CommandIDs: slices.Transform(agentInfo.ShortcutCommand, func(s string) int64 {
|
|
i, _ := conv.StrToInt64(s)
|
|
return i
|
|
}),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
combineInfo.ShortcutCommands = make([]*bot_common.ShortcutCommandInfo, 0, len(shortcutInfos))
|
|
combineInfo.ShortcutCommands = slices.Transform(shortcutInfos, func(si *shortcutEntity.ShortcutCmd) *bot_common.ShortcutCommandInfo {
|
|
url := ""
|
|
if si.ShortcutIcon != nil && si.ShortcutIcon.URI != "" {
|
|
getUrl, e := s.appContext.TosClient.GetObjectUrl(ctx, si.ShortcutIcon.URI)
|
|
if e == nil {
|
|
url = getUrl
|
|
}
|
|
}
|
|
|
|
return &bot_common.ShortcutCommandInfo{
|
|
ID: si.CommandID,
|
|
Name: si.CommandName,
|
|
Description: si.Description,
|
|
IconURL: url,
|
|
QueryTemplate: si.TemplateQuery,
|
|
AgentID: ptr.Of(si.ObjectID),
|
|
Command: si.ShortcutCommand,
|
|
Components: slices.Transform(si.Components, func(i *playground.Components) *bot_common.ShortcutCommandComponent {
|
|
sc := &bot_common.ShortcutCommandComponent{
|
|
Name: i.Name,
|
|
Description: i.Description,
|
|
Type: i.InputType.String(),
|
|
ToolParameter: ptr.Of(i.Parameter),
|
|
Options: i.Options,
|
|
IsHide: i.Hide,
|
|
}
|
|
if i.DefaultValue != nil {
|
|
sc.DefaultValue = ptr.Of(i.DefaultValue.Value)
|
|
}
|
|
return sc
|
|
}),
|
|
}
|
|
})
|
|
|
|
}
|
|
return combineInfo, nil
|
|
}
|
|
|
|
func (s *SingleAgentApplicationService) OpenGetBotInfo(ctx context.Context, req *bot_open_api.OpenGetBotInfoRequest) (*bot_open_api.OpenGetBotInfoResponse, error) {
|
|
resp := new(bot_open_api.OpenGetBotInfoResponse)
|
|
|
|
uid := ctxutil.MustGetUIDFromApiAuthCtx(ctx)
|
|
|
|
connectorID := ptr.From(req.ConnectorID)
|
|
|
|
if connectorID == 0 {
|
|
connectorID = ctxutil.GetApiAuthFromCtx(ctx).ConnectorID
|
|
}
|
|
agentInfo, err := s.getAgentInfo(ctx, req.BotID, connectorID, uid, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp.Data = agentInfo
|
|
return resp, nil
|
|
}
|
|
|