feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
288
backend/application/memory/convertor.go
Normal file
288
backend/application/memory/convertor.go
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* 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 memory
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/base"
|
||||
model "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/database"
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/table"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/memory/database/entity"
|
||||
database "github.com/coze-dev/coze-studio/backend/domain/memory/database/service"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/slices"
|
||||
)
|
||||
|
||||
func convertAddDatabase(req *table.AddDatabaseRequest) *database.CreateDatabaseRequest {
|
||||
fieldItems := make([]*model.FieldItem, 0, len(req.FieldList))
|
||||
for _, field := range req.FieldList {
|
||||
fieldItems = append(fieldItems, &model.FieldItem{
|
||||
Name: field.Name,
|
||||
Desc: field.Desc,
|
||||
Type: field.Type,
|
||||
MustRequired: field.MustRequired,
|
||||
})
|
||||
}
|
||||
|
||||
return &database.CreateDatabaseRequest{
|
||||
Database: &entity.Database{
|
||||
IconURI: req.IconURI,
|
||||
CreatorID: req.CreatorID,
|
||||
SpaceID: req.SpaceID,
|
||||
AppID: req.ProjectID,
|
||||
TableName: req.TableName,
|
||||
TableDesc: req.TableDesc,
|
||||
FieldList: fieldItems,
|
||||
RwMode: req.RwMode,
|
||||
PromptDisabled: req.PromptDisabled,
|
||||
ExtraInfo: req.ExtraInfo,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertDatabaseRes(res *entity.Database) *table.SingleDatabaseResponse {
|
||||
return &table.SingleDatabaseResponse{
|
||||
DatabaseInfo: convertDatabaseRes(res),
|
||||
|
||||
Code: 0,
|
||||
Msg: "success",
|
||||
BaseResp: &base.BaseResp{
|
||||
StatusCode: 0,
|
||||
StatusMessage: "success",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertUpdateDatabase converts the API update request to domain request
|
||||
func ConvertUpdateDatabase(req *table.UpdateDatabaseRequest) *database.UpdateDatabaseRequest {
|
||||
fieldItems := make([]*model.FieldItem, 0, len(req.FieldList))
|
||||
for _, field := range req.FieldList {
|
||||
fieldItems = append(fieldItems, &model.FieldItem{
|
||||
Name: field.Name,
|
||||
Desc: field.Desc,
|
||||
AlterID: field.AlterId,
|
||||
Type: field.Type,
|
||||
MustRequired: field.MustRequired,
|
||||
})
|
||||
}
|
||||
|
||||
return &database.UpdateDatabaseRequest{
|
||||
Database: &entity.Database{
|
||||
ID: req.ID,
|
||||
IconURI: req.IconURI,
|
||||
TableName: req.TableName,
|
||||
TableDesc: req.TableDesc,
|
||||
FieldList: fieldItems,
|
||||
RwMode: req.RwMode,
|
||||
PromptDisabled: req.PromptDisabled,
|
||||
ExtraInfo: req.ExtraInfo,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// convertUpdateDatabaseResult converts the domain update response to API response
|
||||
func convertUpdateDatabaseResult(res *database.UpdateDatabaseResponse) *table.SingleDatabaseResponse {
|
||||
return &table.SingleDatabaseResponse{
|
||||
DatabaseInfo: convertDatabaseRes(res.Database),
|
||||
|
||||
Code: 0,
|
||||
Msg: "success",
|
||||
BaseResp: &base.BaseResp{
|
||||
StatusCode: 0,
|
||||
StatusMessage: "success",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func convertDatabaseRes(db *entity.Database) *table.DatabaseInfo {
|
||||
fieldItems := make([]*table.FieldItem, 0, len(db.FieldList))
|
||||
for _, field := range db.FieldList {
|
||||
fieldItems = append(fieldItems, &table.FieldItem{
|
||||
Name: field.Name,
|
||||
Desc: field.Desc,
|
||||
Type: field.Type,
|
||||
MustRequired: field.MustRequired,
|
||||
AlterId: field.AlterID,
|
||||
IsSystemField: field.IsSystemField,
|
||||
})
|
||||
}
|
||||
|
||||
return &table.DatabaseInfo{
|
||||
ID: db.ID,
|
||||
SpaceID: db.SpaceID,
|
||||
ProjectID: db.AppID,
|
||||
IconURI: db.IconURI,
|
||||
IconURL: db.IconURL,
|
||||
TableName: db.TableName,
|
||||
TableDesc: db.TableDesc,
|
||||
Status: db.Status,
|
||||
CreatorID: db.CreatorID,
|
||||
CreateTime: db.CreatedAtMs,
|
||||
UpdateTime: db.UpdatedAtMs,
|
||||
FieldList: fieldItems,
|
||||
ActualTableName: db.ActualTableName,
|
||||
RwMode: table.BotTableRWMode(db.RwMode),
|
||||
PromptDisabled: db.PromptDisabled,
|
||||
IsVisible: db.IsVisible,
|
||||
DraftID: db.DraftID,
|
||||
ExtraInfo: db.ExtraInfo,
|
||||
IsAddedToBot: db.IsAddedToAgent,
|
||||
DatamodelTableID: getDataModelTableID(db.ActualTableName),
|
||||
}
|
||||
}
|
||||
|
||||
// convertListDatabase converts the API list request to domain request
|
||||
func convertListDatabase(req *table.ListDatabaseRequest) *database.ListDatabaseRequest {
|
||||
dRes := &database.ListDatabaseRequest{
|
||||
SpaceID: req.SpaceID,
|
||||
TableName: req.TableName,
|
||||
TableType: req.TableType,
|
||||
AppID: req.GetProjectID(),
|
||||
Limit: int(req.GetLimit()),
|
||||
Offset: int(req.GetOffset()),
|
||||
}
|
||||
|
||||
if req.CreatorID != nil && *req.CreatorID != 0 {
|
||||
dRes.CreatorID = req.CreatorID
|
||||
}
|
||||
|
||||
if len(req.OrderBy) > 0 {
|
||||
dRes.OrderBy = make([]*model.OrderBy, len(req.OrderBy))
|
||||
for i, order := range req.OrderBy {
|
||||
dRes.OrderBy[i] = &model.OrderBy{
|
||||
Field: order.Field,
|
||||
Direction: order.Direction,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dRes
|
||||
}
|
||||
|
||||
// convertListDatabaseRes converts the domain list response to API response
|
||||
func convertListDatabaseRes(res *database.ListDatabaseResponse, bindDatabases []*entity.Database) *table.ListDatabaseResponse {
|
||||
databaseInfos := make([]*table.DatabaseInfo, 0, len(res.Databases))
|
||||
dbMap := slices.ToMap(bindDatabases, func(e *entity.Database) (int64, *entity.Database) {
|
||||
return e.ID, e
|
||||
})
|
||||
for _, db := range res.Databases {
|
||||
databaseInfo := convertDatabaseRes(db)
|
||||
if _, ok := dbMap[db.ID]; ok {
|
||||
databaseInfo.IsAddedToBot = ptr.Of(true)
|
||||
}
|
||||
databaseInfos = append(databaseInfos, databaseInfo)
|
||||
}
|
||||
|
||||
return &table.ListDatabaseResponse{
|
||||
DatabaseInfoList: databaseInfos,
|
||||
TotalCount: res.TotalCount,
|
||||
|
||||
Code: 0,
|
||||
Msg: "success",
|
||||
BaseResp: &base.BaseResp{
|
||||
StatusCode: 0,
|
||||
StatusMessage: "success",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// convertListDatabaseRecordsRes converts domain ListDatabaseRecordResponse to API ListDatabaseRecordsResponse
|
||||
func convertListDatabaseRecordsRes(res *database.ListDatabaseRecordResponse) *table.ListDatabaseRecordsResponse {
|
||||
apiRes := &table.ListDatabaseRecordsResponse{
|
||||
Data: res.Records,
|
||||
TotalNum: int32(res.TotalCount),
|
||||
HasMore: res.HasMore,
|
||||
FieldList: make([]*table.FieldItem, 0, len(res.FieldList)),
|
||||
|
||||
Code: 0,
|
||||
Msg: "success",
|
||||
BaseResp: &base.BaseResp{
|
||||
StatusCode: 0,
|
||||
StatusMessage: "success",
|
||||
},
|
||||
}
|
||||
|
||||
for _, field := range res.FieldList {
|
||||
apiRes.FieldList = append(apiRes.FieldList, &table.FieldItem{
|
||||
Name: field.Name,
|
||||
Desc: field.Desc,
|
||||
Type: field.Type,
|
||||
MustRequired: field.MustRequired,
|
||||
})
|
||||
}
|
||||
|
||||
return apiRes
|
||||
}
|
||||
|
||||
func getDataModelTableID(actualTableName string) string {
|
||||
tableID := ""
|
||||
tableIDStr := strings.Split(actualTableName, "_")
|
||||
if len(tableIDStr) < 2 {
|
||||
return tableID
|
||||
}
|
||||
|
||||
return tableIDStr[1]
|
||||
}
|
||||
|
||||
func convertToBotTableList(databases []*entity.Database, agentID int64, relationMap map[int64]*model.AgentToDatabase) []*table.BotTable {
|
||||
if len(databases) == 0 {
|
||||
return []*table.BotTable{}
|
||||
}
|
||||
|
||||
botTables := make([]*table.BotTable, 0, len(databases))
|
||||
for _, db := range databases {
|
||||
fieldItems := make([]*table.FieldItem, 0, len(db.FieldList))
|
||||
for _, field := range db.FieldList {
|
||||
fieldItems = append(fieldItems, &table.FieldItem{
|
||||
Name: field.Name,
|
||||
Desc: field.Desc,
|
||||
Type: field.Type,
|
||||
MustRequired: field.MustRequired,
|
||||
AlterId: field.AlterID,
|
||||
IsSystemField: field.IsSystemField,
|
||||
})
|
||||
}
|
||||
|
||||
botTable := &table.BotTable{
|
||||
ID: db.ID,
|
||||
BotID: agentID,
|
||||
TableID: strconv.FormatInt(db.ID, 10),
|
||||
TableName: db.TableName,
|
||||
TableDesc: db.TableDesc,
|
||||
Status: table.BotTableStatus(db.Status),
|
||||
CreatorID: db.CreatorID,
|
||||
CreateTime: db.CreatedAtMs,
|
||||
UpdateTime: db.UpdatedAtMs,
|
||||
FieldList: fieldItems,
|
||||
ActualTableName: db.ActualTableName,
|
||||
RwMode: table.BotTableRWMode(db.RwMode),
|
||||
}
|
||||
|
||||
if r, ok := relationMap[db.ID]; ok {
|
||||
botTable.ExtraInfo = map[string]string{
|
||||
"prompt_disabled": fmt.Sprintf("%t", r.PromptDisabled),
|
||||
}
|
||||
}
|
||||
|
||||
botTables = append(botTables, botTable)
|
||||
}
|
||||
|
||||
return botTables
|
||||
}
|
||||
1033
backend/application/memory/database.go
Normal file
1033
backend/application/memory/database.go
Normal file
File diff suppressed because it is too large
Load Diff
64
backend/application/memory/init.go
Normal file
64
backend/application/memory/init.go
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 memory
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
|
||||
database "github.com/coze-dev/coze-studio/backend/domain/memory/database/service"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/repository"
|
||||
variables "github.com/coze-dev/coze-studio/backend/domain/memory/variables/service"
|
||||
search "github.com/coze-dev/coze-studio/backend/domain/search/service"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/idgen"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/rdb"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/storage"
|
||||
rdbService "github.com/coze-dev/coze-studio/backend/infra/impl/rdb"
|
||||
)
|
||||
|
||||
type MemoryApplicationServices struct {
|
||||
VariablesDomainSVC variables.Variables
|
||||
DatabaseDomainSVC database.Database
|
||||
RDBDomainSVC rdb.RDB
|
||||
}
|
||||
|
||||
type ServiceComponents struct {
|
||||
IDGen idgen.IDGenerator
|
||||
DB *gorm.DB
|
||||
EventBus search.ResourceEventBus
|
||||
TosClient storage.Storage
|
||||
ResourceDomainNotifier search.ResourceEventBus
|
||||
CacheCli *redis.Client
|
||||
}
|
||||
|
||||
func InitService(c *ServiceComponents) *MemoryApplicationServices {
|
||||
repo := repository.NewVariableRepo(c.DB, c.IDGen)
|
||||
variablesDomainSVC := variables.NewService(repo)
|
||||
rdbSVC := rdbService.NewService(c.DB, c.IDGen)
|
||||
databaseDomainSVC := database.NewService(rdbSVC, c.DB, c.IDGen, c.TosClient, c.CacheCli)
|
||||
|
||||
VariableApplicationSVC.DomainSVC = variablesDomainSVC
|
||||
DatabaseApplicationSVC.DomainSVC = databaseDomainSVC
|
||||
DatabaseApplicationSVC.eventbus = c.ResourceDomainNotifier
|
||||
|
||||
return &MemoryApplicationServices{
|
||||
VariablesDomainSVC: variablesDomainSVC,
|
||||
DatabaseDomainSVC: databaseDomainSVC,
|
||||
RDBDomainSVC: rdbSVC,
|
||||
}
|
||||
}
|
||||
385
backend/application/memory/variables.go
Normal file
385
backend/application/memory/variables.go
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* 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 memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/base"
|
||||
model "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/variables"
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/kvmemory"
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/project_memory"
|
||||
"github.com/coze-dev/coze-studio/backend/application/base/ctxutil"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/entity"
|
||||
variables "github.com/coze-dev/coze-studio/backend/domain/memory/variables/service"
|
||||
"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/ternary"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/logs"
|
||||
"github.com/coze-dev/coze-studio/backend/types/consts"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
type VariableApplicationService struct {
|
||||
DomainSVC variables.Variables
|
||||
}
|
||||
|
||||
var VariableApplicationSVC = VariableApplicationService{}
|
||||
|
||||
var i18nLocal2GroupVariableInfo = map[i18n.Locale]map[project_memory.VariableChannel]project_memory.GroupVariableInfo{
|
||||
i18n.LocaleEN: {
|
||||
project_memory.VariableChannel_APP: {
|
||||
GroupName: "App variable",
|
||||
GroupDesc: "Configures data accessed across multiple development scenarios in the app. It is initialized to a default value each time a new request is sent.",
|
||||
},
|
||||
project_memory.VariableChannel_Custom: {
|
||||
GroupName: "User variable",
|
||||
GroupDesc: "Persistently stores and reads project date for users, such as the preferred language and custom settings.",
|
||||
},
|
||||
project_memory.VariableChannel_System: {
|
||||
GroupName: "System variable",
|
||||
GroupDesc: "Displays the data that you enabled as needed, which can be used to identify users via IDs or handle channel-specific features. The data is automatically generated and is read-only.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var channel2GroupVariableInfo = map[project_memory.VariableChannel]project_memory.GroupVariableInfo{
|
||||
project_memory.VariableChannel_APP: {
|
||||
GroupName: "应用变量",
|
||||
GroupDesc: "用于配置应用中多处开发场景需要访问的数据,每次新请求均会初始化为默认值。",
|
||||
GroupExtDesc: "",
|
||||
IsReadOnly: false,
|
||||
SubGroupList: []*project_memory.GroupVariableInfo{},
|
||||
VarInfoList: []*project_memory.Variable{},
|
||||
},
|
||||
project_memory.VariableChannel_Custom: {
|
||||
GroupName: "用户变量",
|
||||
GroupDesc: "用于存储每个用户使用项目过程中,需要持久化存储和读取的数据,如用户的语言偏好、个性化设置等。",
|
||||
GroupExtDesc: "",
|
||||
IsReadOnly: false,
|
||||
SubGroupList: []*project_memory.GroupVariableInfo{},
|
||||
VarInfoList: []*project_memory.Variable{},
|
||||
},
|
||||
project_memory.VariableChannel_System: {
|
||||
GroupName: "系统变量",
|
||||
GroupDesc: "可选择开启你需要获取的,系统在用户在请求自动产生的数据,仅可读不可修改。如用于通过ID识别用户或处理某些渠道特有的功能。",
|
||||
GroupExtDesc: "",
|
||||
IsReadOnly: true,
|
||||
SubGroupList: []*project_memory.GroupVariableInfo{},
|
||||
VarInfoList: []*project_memory.Variable{},
|
||||
},
|
||||
}
|
||||
|
||||
func (v *VariableApplicationService) GetSysVariableConf(ctx context.Context, req *kvmemory.GetSysVariableConfRequest) (*kvmemory.GetSysVariableConfResponse, error) {
|
||||
vars := v.DomainSVC.GetSysVariableConf(ctx)
|
||||
|
||||
return &kvmemory.GetSysVariableConfResponse{
|
||||
Conf: vars,
|
||||
GroupConf: vars.GroupByName(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *VariableApplicationService) GetProjectVariablesMeta(ctx context.Context, appOwnerID int64, req *project_memory.GetProjectVariableListReq) (*project_memory.GetProjectVariableListResp, error) {
|
||||
uid := ctxutil.GetUIDFromCtx(ctx)
|
||||
if uid == nil {
|
||||
return nil, errorx.New(errno.ErrMemoryPermissionCode, errorx.KV("msg", "session required"))
|
||||
}
|
||||
|
||||
version := ""
|
||||
if req.Version != 0 {
|
||||
version = fmt.Sprintf("%d", req.Version)
|
||||
}
|
||||
|
||||
meta, err := v.DomainSVC.GetProjectVariablesMeta(ctx, req.ProjectID, version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
groupConf, err := v.toGroupVariableInfo(ctx, meta)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &project_memory.GetProjectVariableListResp{
|
||||
VariableList: meta.ToProjectVariables(),
|
||||
GroupConf: groupConf,
|
||||
CanEdit: appOwnerID == *uid,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *VariableApplicationService) getGroupVariableConf(ctx context.Context, channel project_memory.VariableChannel) project_memory.GroupVariableInfo {
|
||||
groupConf, ok := channel2GroupVariableInfo[channel]
|
||||
if !ok {
|
||||
return project_memory.GroupVariableInfo{}
|
||||
}
|
||||
|
||||
local := i18n.GetLocale(ctx)
|
||||
i18nConf, ok := i18nLocal2GroupVariableInfo[local][channel]
|
||||
if ok {
|
||||
groupConf.GroupName = i18nConf.GroupName
|
||||
groupConf.GroupDesc = i18nConf.GroupDesc
|
||||
}
|
||||
|
||||
return groupConf
|
||||
}
|
||||
|
||||
func (v *VariableApplicationService) toGroupVariableInfo(ctx context.Context, meta *entity.VariablesMeta) ([]*project_memory.GroupVariableInfo, error) {
|
||||
channel2Vars := meta.GroupByChannel()
|
||||
groupConfList := make([]*project_memory.GroupVariableInfo, 0, len(channel2Vars))
|
||||
|
||||
showChannels := []project_memory.VariableChannel{
|
||||
project_memory.VariableChannel_APP,
|
||||
project_memory.VariableChannel_Custom,
|
||||
project_memory.VariableChannel_System,
|
||||
}
|
||||
|
||||
for _, channel := range showChannels {
|
||||
ch := channel
|
||||
vars := channel2Vars[ch]
|
||||
groupConf := v.getGroupVariableConf(ctx, ch)
|
||||
groupConf.DefaultChannel = &ch
|
||||
if channel != project_memory.VariableChannel_System {
|
||||
groupConf.VarInfoList = vars
|
||||
groupConfList = append(groupConfList, &groupConf)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
key2Var := make(map[string]*project_memory.Variable)
|
||||
for _, v := range vars {
|
||||
key2Var[v.Keyword] = v
|
||||
}
|
||||
|
||||
// project_memory.VariableChannel_System
|
||||
sysVars := v.DomainSVC.GetSysVariableConf(ctx).RemoveLocalChannelVariable()
|
||||
groupName2Group := sysVars.GroupByName()
|
||||
subGroupList := make([]*project_memory.GroupVariableInfo, 0, len(groupName2Group))
|
||||
|
||||
for _, group := range groupName2Group {
|
||||
var e entity.SysConfVariables = group.VarInfoList
|
||||
varList := make([]*project_memory.Variable, 0, len(group.VarInfoList))
|
||||
|
||||
for _, defaultSysMeta := range e.ToVariables().ToProjectVariables() {
|
||||
sysMetaInUserConf := key2Var[defaultSysMeta.Keyword]
|
||||
if sysMetaInUserConf == nil {
|
||||
varList = append(varList, defaultSysMeta)
|
||||
} else {
|
||||
varList = append(varList, sysMetaInUserConf)
|
||||
}
|
||||
}
|
||||
|
||||
pGroupVariableInfo := &project_memory.GroupVariableInfo{
|
||||
GroupName: group.GroupName,
|
||||
GroupDesc: group.GroupDesc,
|
||||
GroupExtDesc: group.GroupExtDesc,
|
||||
IsReadOnly: true,
|
||||
VarInfoList: varList,
|
||||
}
|
||||
|
||||
subGroupList = append(subGroupList, pGroupVariableInfo)
|
||||
}
|
||||
|
||||
groupConf.SubGroupList = subGroupList
|
||||
groupConfList = append(groupConfList, &groupConf)
|
||||
}
|
||||
|
||||
return groupConfList, nil
|
||||
}
|
||||
|
||||
func (v *VariableApplicationService) UpdateProjectVariable(ctx context.Context, req project_memory.UpdateProjectVariableReq) (*project_memory.UpdateProjectVariableResp, error) {
|
||||
uid := ctxutil.GetUIDFromCtx(ctx)
|
||||
if uid == nil {
|
||||
return nil, errorx.New(errno.ErrMemoryPermissionCode, errorx.KV("msg", "session required"))
|
||||
}
|
||||
|
||||
if req.UserID == 0 {
|
||||
req.UserID = *uid
|
||||
}
|
||||
|
||||
// TODO: project owner check
|
||||
|
||||
sysVars := v.DomainSVC.GetSysVariableConf(ctx).ToVariables()
|
||||
|
||||
sysVarsKeys2Meta := make(map[string]*entity.VariableMeta)
|
||||
for _, v := range sysVars.Variables {
|
||||
sysVarsKeys2Meta[v.Keyword] = v
|
||||
}
|
||||
|
||||
list := make([]*project_memory.Variable, 0, len(req.VariableList))
|
||||
for _, v := range req.VariableList {
|
||||
if v.Channel == project_memory.VariableChannel_System &&
|
||||
sysVarsKeys2Meta[v.Keyword] == nil {
|
||||
logs.CtxInfof(ctx, "sys variable not found, keyword: %s", v.Keyword)
|
||||
continue
|
||||
}
|
||||
|
||||
list = append(list, v)
|
||||
}
|
||||
|
||||
key2Var := make(map[string]*project_memory.Variable)
|
||||
for _, v := range req.VariableList {
|
||||
key2Var[v.Keyword] = v
|
||||
}
|
||||
|
||||
for _, v := range sysVars.Variables {
|
||||
if key2Var[v.Keyword] == nil {
|
||||
list = append(list, v.ToProjectVariable())
|
||||
} else {
|
||||
if key2Var[v.Keyword].DefaultValue != v.DefaultValue ||
|
||||
key2Var[v.Keyword].VariableType != v.VariableType {
|
||||
return nil, errorx.New(errno.ErrMemoryPermissionCode, errorx.KV("msg", "can not update system variable"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, vv := range list {
|
||||
if vv.Channel == project_memory.VariableChannel_APP {
|
||||
e := entity.NewVariableMeta(vv)
|
||||
err := e.CheckSchema(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err := v.DomainSVC.UpsertProjectMeta(ctx, req.ProjectID, "", req.UserID, entity.NewVariables(list))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &project_memory.UpdateProjectVariableResp{
|
||||
Code: 0,
|
||||
Msg: "success",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *VariableApplicationService) GetVariableMeta(ctx context.Context, req *project_memory.GetMemoryVariableMetaReq) (*project_memory.GetMemoryVariableMetaResp, error) {
|
||||
vars, err := v.DomainSVC.GetVariableMeta(ctx, req.ConnectorID, req.ConnectorType, req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vars.RemoveDisableVariable()
|
||||
|
||||
return &project_memory.GetMemoryVariableMetaResp{
|
||||
VariableMap: vars.GroupByChannel(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *VariableApplicationService) DeleteVariableInstance(ctx context.Context, req *kvmemory.DelProfileMemoryRequest) (*kvmemory.DelProfileMemoryResponse, error) {
|
||||
uid := ctxutil.GetUIDFromCtx(ctx)
|
||||
if uid == nil {
|
||||
return nil, errorx.New(errno.ErrMemoryPermissionCode, errorx.KV("msg", "session required"))
|
||||
}
|
||||
|
||||
bizType := ternary.IFElse(req.BotID == 0, project_memory.VariableConnector_Project, project_memory.VariableConnector_Bot)
|
||||
bizID := ternary.IFElse(req.BotID == 0, req.ProjectID, fmt.Sprintf("%d", req.BotID))
|
||||
|
||||
e := entity.NewUserVariableMeta(&model.UserVariableMeta{
|
||||
BizType: bizType,
|
||||
BizID: bizID,
|
||||
Version: "",
|
||||
ConnectorID: req.GetConnectorID(),
|
||||
ConnectorUID: fmt.Sprintf("%d", *uid),
|
||||
})
|
||||
|
||||
err := v.DomainSVC.DeleteVariableInstance(ctx, e, req.Keywords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &kvmemory.DelProfileMemoryResponse{}, nil
|
||||
}
|
||||
|
||||
func (v *VariableApplicationService) GetPlayGroundMemory(ctx context.Context, req *kvmemory.GetProfileMemoryRequest) (*kvmemory.GetProfileMemoryResponse, error) {
|
||||
uid := ctxutil.GetUIDFromCtx(ctx)
|
||||
if uid == nil {
|
||||
return nil, errorx.New(errno.ErrMemoryPermissionCode, errorx.KV("msg", "session required"))
|
||||
}
|
||||
|
||||
isProjectKV := req.ProjectID != nil
|
||||
versionStr := strconv.FormatInt(req.GetProjectVersion(), 10)
|
||||
if req.GetProjectVersion() == 0 {
|
||||
versionStr = ""
|
||||
}
|
||||
|
||||
bizType := ternary.IFElse(isProjectKV, project_memory.VariableConnector_Project, project_memory.VariableConnector_Bot)
|
||||
bizID := ternary.IFElse(isProjectKV, req.GetProjectID(), fmt.Sprintf("%d", req.BotID))
|
||||
version := ternary.IFElse(isProjectKV, versionStr, "")
|
||||
connectId := ternary.IFElse(req.ConnectorID == nil, consts.CozeConnectorID, req.GetConnectorID())
|
||||
connectorUID := ternary.IFElse(req.UserID == 0, *uid, req.UserID)
|
||||
|
||||
e := entity.NewUserVariableMeta(&model.UserVariableMeta{
|
||||
BizType: bizType,
|
||||
BizID: bizID,
|
||||
Version: version,
|
||||
ConnectorID: connectId,
|
||||
ConnectorUID: fmt.Sprintf("%d", connectorUID),
|
||||
})
|
||||
|
||||
res, err := v.DomainSVC.GetVariableChannelInstance(ctx, e, req.Keywords, req.VariableChannel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &kvmemory.GetProfileMemoryResponse{
|
||||
Memories: res,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *VariableApplicationService) SetVariableInstance(ctx context.Context, req *kvmemory.SetKvMemoryReq) (*kvmemory.SetKvMemoryResp, error) {
|
||||
uid := ctxutil.GetUIDFromCtx(ctx)
|
||||
if uid == nil {
|
||||
return nil, errorx.New(errno.ErrMemoryPermissionCode, errorx.KV("msg", "session required"))
|
||||
}
|
||||
|
||||
isProjectKV := req.ProjectID != nil
|
||||
versionStr := strconv.FormatInt(req.GetProjectVersion(), 10)
|
||||
if req.GetProjectVersion() == 0 {
|
||||
versionStr = ""
|
||||
}
|
||||
|
||||
bizType := ternary.IFElse(isProjectKV, project_memory.VariableConnector_Project, project_memory.VariableConnector_Bot)
|
||||
bizID := ternary.IFElse(isProjectKV, req.GetProjectID(), fmt.Sprintf("%d", req.BotID))
|
||||
version := ternary.IFElse(isProjectKV, versionStr, "")
|
||||
connectId := ternary.IFElse(req.ConnectorID == nil, consts.CozeConnectorID, req.GetConnectorID())
|
||||
connectorUID := ternary.IFElse(req.GetUserID() == 0, *uid, req.GetUserID())
|
||||
|
||||
e := entity.NewUserVariableMeta(&model.UserVariableMeta{
|
||||
BizType: bizType,
|
||||
BizID: bizID,
|
||||
Version: version,
|
||||
ConnectorID: connectId,
|
||||
ConnectorUID: fmt.Sprintf("%d", connectorUID),
|
||||
})
|
||||
|
||||
exitKeys, err := v.DomainSVC.SetVariableInstance(ctx, e, req.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
exitKeysStr, _ := json.Marshal(exitKeys)
|
||||
|
||||
return &kvmemory.SetKvMemoryResp{
|
||||
BaseResp: &base.BaseResp{
|
||||
Extra: map[string]string{"existKeys": string(exitKeysStr)},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user