coze-studio/backend/application/singleagent/single_agent.go

734 lines
22 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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/crossdomain/database"
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/plugin"
intelligence "github.com/coze-dev/coze-studio/backend/api/model/intelligence/common"
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/bot_common"
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/developer_api"
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/playground"
"github.com/coze-dev/coze-studio/backend/api/model/table"
"github.com/coze-dev/coze-studio/backend/application/base/ctxutil"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossdatabase"
"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: 错误码
}
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: 错误码
}
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
}
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: bot_common.BotMode_SingleMode,
BackgroundImageInfoList: do.BackgroundImageInfoList,
Status: bot_common.BotStatus_Using,
DatabaseList: do.Database,
ShortcutSort: do.ShortcutCommand,
}
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 {
uid = ptr.Of(int64(888))
// 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) : user domain 补完以后再改
// 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 *playground.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
}
agentInfo, err := s.DomainSVC.ObtainAgentByIdentity(ctx, &entity.AgentIdentity{
AgentID: req.BotID,
ConnectorID: connectorID,
Version: ptr.From(req.Version),
})
if err != nil {
return nil, err
}
if agentInfo == nil {
logs.CtxErrorf(ctx, "agent(%d) is not exist", req.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 {
return &bot_common.ShortcutCommandComponent{
Name: i.Name,
Description: i.Description,
Type: i.InputType.String(),
ToolParameter: ptr.Of(i.Parameter),
Options: i.Options,
DefaultValue: ptr.Of(i.DefaultValue.Value),
IsHide: i.Hide,
}
}),
}
})
}
return combineInfo, nil
}