feat: manually mirror opencoze's code from bytedance

Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
fanlv
2025-07-20 17:36:12 +08:00
commit 890153324f
14811 changed files with 1923430 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
/*
* 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 entity
import (
"sort"
"strings"
"github.com/coze-dev/coze-studio/backend/api/model/kvmemory"
"github.com/coze-dev/coze-studio/backend/api/model/project_memory"
)
type SysConfVariables []*kvmemory.VariableInfo
func (v SysConfVariables) ToVariables() *VariablesMeta {
vars := make([]*VariableMeta, 0)
for _, vv := range v {
if vv == nil {
continue
}
tmp := &VariableMeta{
Keyword: vv.Key,
Description: vv.Description,
DefaultValue: vv.DefaultValue,
VariableType: project_memory.VariableType_KVVariable,
Channel: project_memory.VariableChannel_System,
IsReadOnly: true,
EffectiveChannelList: vv.EffectiveChannelList,
}
tmp.SetupSchema()
vars = append(vars, tmp)
}
return &VariablesMeta{
Variables: vars,
}
}
func (v SysConfVariables) GroupByName() []*kvmemory.GroupVariableInfo {
groups := make(map[string]*kvmemory.GroupVariableInfo)
for _, variable := range v {
if variable == nil {
continue
}
groupName := variable.GroupName
if groupName == "" {
groupName = "未分组" // 处理空分组名
}
if _, ok := groups[groupName]; !ok {
groups[groupName] = &kvmemory.GroupVariableInfo{
GroupName: groupName,
GroupDesc: variable.GroupDesc,
VarInfoList: []*kvmemory.VariableInfo{},
}
}
groups[groupName].VarInfoList = append(groups[groupName].VarInfoList, variable)
}
// 转换为切片并按组名排序
result := make([]*kvmemory.GroupVariableInfo, 0, len(groups))
for _, group := range groups {
result = append(result, group)
}
// 可选:按组名排序
sort.Slice(result, func(i, j int) bool {
return result[i].GroupName < result[j].GroupName
})
return result
}
func (v SysConfVariables) RemoveLocalChannelVariable() SysConfVariables {
var res []*kvmemory.VariableInfo
for _, vv := range v {
ch := v.genChannelFromName(vv.Key)
if ch == project_memory.VariableChannel_Location {
continue
}
res = append(res, vv)
}
return res
}
func (v SysConfVariables) genChannelFromName(name string) project_memory.VariableChannel {
if strings.Contains(name, "lark") {
return project_memory.VariableChannel_Feishu
} else if strings.Contains(name, "lon") || strings.Contains(name, "lat") {
return project_memory.VariableChannel_Location
}
return project_memory.VariableChannel_System
}

View File

@@ -0,0 +1,121 @@
/*
* 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 entity
import (
"context"
"encoding/base64"
"fmt"
"strconv"
"strings"
"time"
"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/pkg/errorx"
"github.com/coze-dev/coze-studio/backend/types/errno"
)
type UserVariableMeta struct {
*variables.UserVariableMeta
}
func NewUserVariableMeta(v *variables.UserVariableMeta) *UserVariableMeta {
return &UserVariableMeta{
UserVariableMeta: v,
}
}
type VariableInstance struct {
ID int64
BizType project_memory.VariableConnector
BizID string
Version string
Keyword string
Type int32
Content string
ConnectorUID string
ConnectorID int64
CreatedAt int64
UpdatedAt int64
}
const (
sysUUIDKey string = "sys_uuid"
)
func (v *UserVariableMeta) GenSystemKV(ctx context.Context, keyword string) (*kvmemory.KVItem, error) {
if keyword != sysUUIDKey { // 外场暂时只支持这一个变量
return nil, nil
}
return v.genUUID(ctx)
}
func (v *UserVariableMeta) genUUID(ctx context.Context) (*kvmemory.KVItem, error) {
if v.BizID == "" {
return nil, errorx.New(errno.ErrMemoryGetSysUUIDInstanceCode, errorx.KV("msg", "biz_id is empty"))
}
if v.ConnectorUID == "" {
return nil, errorx.New(errno.ErrMemoryGetSysUUIDInstanceCode, errorx.KV("msg", "connector_uid is empty"))
}
if v.ConnectorID == 0 {
return nil, errorx.New(errno.ErrMemoryGetSysUUIDInstanceCode, errorx.KV("msg", "connector_id is empty"))
}
encryptSysUUIDKey := v.encryptSysUUIDKey(ctx)
now := time.Now().Unix()
return &kvmemory.KVItem{
Keyword: sysUUIDKey,
Value: encryptSysUUIDKey,
Schema: stringSchema,
CreateTime: now,
UpdateTime: now,
IsSystem: true,
}, nil
}
func (v *UserVariableMeta) encryptSysUUIDKey(ctx context.Context) string {
// 拼接四个字段,中间用特殊分隔符(如 |
plain := fmt.Sprintf("%d|%s|%s|%d", v.BizType, v.BizID, v.ConnectorUID, v.ConnectorID)
return base64.StdEncoding.EncodeToString([]byte(plain))
}
func (v *UserVariableMeta) DecryptSysUUIDKey(ctx context.Context, encryptSysUUIDKey string) *VariableInstance {
data, err := base64.StdEncoding.DecodeString(encryptSysUUIDKey)
if err != nil {
return nil
}
parts := strings.Split(string(data), "|")
if len(parts) != 4 {
return nil
}
bizType64, _ := strconv.ParseInt(parts[0], 10, 32)
connectorID, _ := strconv.ParseInt(parts[3], 10, 64)
return &VariableInstance{
BizType: project_memory.VariableConnector(bizType64),
BizID: parts[1],
ConnectorUID: parts[2],
ConnectorID: connectorID,
}
}

View File

@@ -0,0 +1,98 @@
/*
* 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 entity
import (
"context"
"fmt"
"github.com/coze-dev/coze-studio/backend/api/model/project_memory"
)
type VariableMeta struct {
Keyword string
DefaultValue string
VariableType project_memory.VariableType
Channel project_memory.VariableChannel
Description string
Enable bool
EffectiveChannelList []string
Schema string
IsReadOnly bool
PromptDisabled bool
}
func NewVariableMeta(e *project_memory.Variable) *VariableMeta {
return &VariableMeta{
Keyword: e.Keyword,
DefaultValue: e.DefaultValue,
VariableType: e.VariableType,
Channel: e.Channel,
Description: e.Description,
Enable: e.Enable,
EffectiveChannelList: e.EffectiveChannelList,
Schema: e.Schema,
IsReadOnly: e.IsReadOnly,
}
}
func (v *VariableMeta) ToProjectVariable() *project_memory.Variable {
return &project_memory.Variable{
Keyword: v.Keyword,
DefaultValue: v.DefaultValue,
VariableType: v.VariableType,
Channel: v.Channel,
Description: v.Description,
Enable: v.Enable,
EffectiveChannelList: v.EffectiveChannelList,
Schema: v.Schema,
IsReadOnly: v.IsReadOnly,
}
}
func (v *VariableMeta) GetSchema(ctx context.Context) (*VariableMetaSchema, error) {
return NewVariableMetaSchema([]byte(v.Schema))
}
func (v *VariableMeta) CheckSchema(ctx context.Context) error {
schema, err := NewVariableMetaSchema([]byte(v.Schema))
if err != nil {
return err
}
return schema.check(ctx)
}
const stringSchema = "{\n \"type\": \"string\",\n \"name\": \"%v\",\n \"required\": false\n}"
func (v *VariableMeta) SetupSchema() {
if v.Schema == "" {
v.Schema = fmt.Sprintf(stringSchema, v.Keyword)
}
}
func (v *VariableMeta) SetupIsReadOnly() {
if v.Channel == project_memory.VariableChannel_Feishu ||
v.Channel == project_memory.VariableChannel_Location ||
v.Channel == project_memory.VariableChannel_System {
v.IsReadOnly = true
}
}
func (v *VariableMeta) IsSystem() bool {
return v.Channel == project_memory.VariableChannel_System
}

View File

@@ -0,0 +1,177 @@
/*
* 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 entity
import (
"context"
"encoding/json"
"regexp"
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
"github.com/coze-dev/coze-studio/backend/types/errno"
)
const (
variableMetaSchemaTypeObject = "object"
variableMetaSchemaTypeArray = "list"
variableMetaSchemaTypeInteger = "integer"
variableMetaSchemaTypeString = "string"
variableMetaSchemaTypeBoolean = "boolean"
variableMetaSchemaTypeNumber = "float"
)
// TODO: remove me later
// {"name":"app_var_arr","enable":true,"description":"121222","type":"list","readonly":false,"schema":{"type":"integer"}}
type VariableMetaSchema struct {
Type string `json:"type,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Readonly bool `json:"readonly,omitempty"`
Enable bool `json:"enable,omitempty"`
Schema json.RawMessage `json:"schema,omitempty"`
}
func NewVariableMetaSchema(schema []byte) (*VariableMetaSchema, error) {
schemaObj := &VariableMetaSchema{}
err := json.Unmarshal(schema, schemaObj)
if err != nil {
return nil, errorx.New(errno.ErrMemorySchemeInvalidCode, errorx.KVf("msg", "schema json invalid: %s \n json = %s", err.Error(), string(schema)))
}
return schemaObj, nil
}
func (v *VariableMetaSchema) IsArrayType() bool {
return v.Type == variableMetaSchemaTypeArray
}
// GetArrayType e.g. schema = {"type":"int"}
func (v *VariableMetaSchema) GetArrayType(schema []byte) (string, error) {
schemaObj, err := NewVariableMetaSchema(schema)
if err != nil {
return "", errorx.New(errno.ErrMemorySchemeInvalidCode, errorx.KVf("msg", "NewVariableMetaSchema failed, %v", err.Error()))
}
if schemaObj.Type == "" {
return "", errorx.New(errno.ErrMemorySchemeInvalidCode, errorx.KVf("msg", "array type not found in %s", schema))
}
return schemaObj.Type, nil
}
func (v *VariableMetaSchema) IsStringType() bool {
return v.Type == variableMetaSchemaTypeString
}
func (v *VariableMetaSchema) IsIntegerType() bool {
return v.Type == variableMetaSchemaTypeInteger
}
func (v *VariableMetaSchema) IsBooleanType() bool {
return v.Type == variableMetaSchemaTypeBoolean
}
func (v *VariableMetaSchema) IsNumberType() bool {
return v.Type == variableMetaSchemaTypeNumber
}
func (v *VariableMetaSchema) IsObjectType() bool {
return v.Type == variableMetaSchemaTypeObject
}
// GetObjetProperties e.g. schema = [{"name":"app_var_12_sdd","enable":true,"description":"s22","type":"string","readonly":false,"schema":""}]
func (v *VariableMetaSchema) GetObjectProperties(schema []byte) (map[string]*VariableMetaSchema, error) {
schemas := make([]*VariableMetaSchema, 0)
err := json.Unmarshal(schema, &schemas)
if err != nil {
return nil, errorx.New(errno.ErrMemorySchemeInvalidCode, errorx.KV("msg", "schema array content json invalid"))
}
properties := make(map[string]*VariableMetaSchema)
for _, schemaObj := range schemas {
properties[schemaObj.Name] = schemaObj
}
return properties, nil
}
func (v *VariableMetaSchema) check(ctx context.Context) error {
return v.checkAppVariableSchema(ctx, v, "")
}
func (v *VariableMetaSchema) checkAppVariableSchema(ctx context.Context, schemaObj *VariableMetaSchema, schema string) (err error) {
if len(schema) == 0 && schemaObj == nil {
return errorx.New(errno.ErrMemorySchemeInvalidCode, errorx.KV("msg", "schema is nil"))
}
if schemaObj == nil {
schemaObj, err = NewVariableMetaSchema([]byte(schema))
if err != nil {
return errorx.New(errno.ErrMemorySchemeInvalidCode, errorx.KVf("msg", "checkAppVariableSchema failed , %v", err.Error()))
}
}
if !schemaObj.nameValidate() {
return errorx.New(errno.ErrMemorySchemeInvalidCode, errorx.KVf("msg", "name(%s) is invalid", schemaObj.Name))
}
if schemaObj.Type == variableMetaSchemaTypeObject {
return v.checkSchemaObj(ctx, schemaObj.Schema)
} else if schemaObj.Type == variableMetaSchemaTypeArray {
_, err := v.GetArrayType(schemaObj.Schema)
if err != nil {
return errorx.New(errno.ErrMemorySchemeInvalidCode, errorx.KVf("msg", "GetArrayType failed : %v", err.Error()))
}
}
return nil
}
func (v *VariableMetaSchema) checkSchemaObj(ctx context.Context, schema []byte) error {
properties, err := v.GetObjectProperties(schema)
if err != nil {
return errorx.New(errno.ErrMemorySchemeInvalidCode, errorx.KVf("msg", "GetObjectProperties failed : %v", err.Error()))
}
for _, schemaObj := range properties {
if err := v.checkAppVariableSchema(ctx, schemaObj, ""); err != nil {
return err
}
}
return nil
}
func (v *VariableMetaSchema) nameValidate() bool {
identifier := v.Name
reservedWords := map[string]bool{
"true": true, "false": true, "and": true, "AND": true,
"or": true, "OR": true, "not": true, "NOT": true,
"null": true, "nil": true, "If": true, "Switch": true,
}
if reservedWords[identifier] {
return false
}
// 检查是否符合后面的部分正则规则
pattern := `^[a-zA-Z_][a-zA-Z_$0-9]*$`
match, _ := regexp.MatchString(pattern, identifier)
return match
}

View File

@@ -0,0 +1,160 @@
/*
* 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 entity
import (
"fmt"
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/bot_common"
"github.com/coze-dev/coze-studio/backend/api/model/project_memory"
)
type VariablesMeta struct {
ID int64
CreatorID int64
BizType project_memory.VariableConnector
BizID string
CreatedAt int64
UpdatedAt int64
Version string
Variables []*VariableMeta
}
func NewVariablesWithAgentVariables(vars []*bot_common.Variable) *VariablesMeta {
res := make([]*VariableMeta, 0)
for _, variable := range vars {
res = append(res, agentVariableMetaToProjectVariableMeta(variable))
}
return &VariablesMeta{
Variables: res,
}
}
func NewVariables(vars []*project_memory.Variable) *VariablesMeta {
res := make([]*VariableMeta, 0)
for _, variable := range vars {
res = append(res, &VariableMeta{
Keyword: variable.Keyword,
DefaultValue: variable.DefaultValue,
VariableType: variable.VariableType,
Channel: variable.Channel,
Description: variable.Description,
Enable: variable.Enable,
EffectiveChannelList: variable.EffectiveChannelList,
Schema: variable.Schema,
IsReadOnly: variable.IsReadOnly,
})
}
return &VariablesMeta{
Variables: res,
}
}
func (v *VariablesMeta) ToAgentVariables() []*bot_common.Variable {
res := make([]*bot_common.Variable, 0, len(v.Variables))
for idx := range v.Variables {
v := v.Variables[idx]
isSystem := v.Channel == project_memory.VariableChannel_System
isDisabled := !v.Enable
agentVariable := &bot_common.Variable{
Key: &v.Keyword,
DefaultValue: &v.DefaultValue,
Description: &v.Description,
IsDisabled: &isDisabled,
IsSystem: &isSystem,
PromptDisabled: &v.PromptDisabled,
}
res = append(res, agentVariable)
}
return res
}
func (v *VariablesMeta) ToProjectVariables() []*project_memory.Variable {
res := make([]*project_memory.Variable, 0, len(v.Variables))
for _, v := range v.Variables {
res = append(res, v.ToProjectVariable())
}
return res
}
func (v *VariablesMeta) SetupIsReadOnly() {
for _, variable := range v.Variables {
variable.SetupIsReadOnly()
}
}
func (v *VariablesMeta) SetupSchema() {
for _, variable := range v.Variables {
variable.SetupSchema()
}
}
func agentVariableMetaToProjectVariableMeta(variable *bot_common.Variable) *VariableMeta {
temp := &VariableMeta{
Keyword: variable.GetKey(),
DefaultValue: variable.GetDefaultValue(),
VariableType: project_memory.VariableType_KVVariable,
Description: variable.GetDescription(),
Enable: !variable.GetIsDisabled(),
Schema: fmt.Sprintf(stringSchema, variable.GetKey()),
PromptDisabled: variable.GetPromptDisabled(),
}
if variable.GetIsSystem() {
temp.IsReadOnly = true
temp.Channel = project_memory.VariableChannel_System
} else {
temp.Channel = project_memory.VariableChannel_Custom
}
return temp
}
func (v *VariablesMeta) GroupByChannel() map[project_memory.VariableChannel][]*project_memory.Variable {
res := make(map[project_memory.VariableChannel][]*project_memory.Variable)
for _, variable := range v.Variables {
ch := variable.Channel
res[ch] = append(res[ch], variable.ToProjectVariable())
}
return res
}
func (v *VariablesMeta) RemoveDisableVariable() {
var res []*VariableMeta
for _, vv := range v.Variables {
if vv.Enable {
res = append(res, vv)
}
}
v.Variables = res
}
func (v *VariablesMeta) FilterChannelVariable(ch project_memory.VariableChannel) {
var res []*VariableMeta
for _, vv := range v.Variables {
if vv.Channel != ch {
continue
}
res = append(res, vv)
}
v.Variables = res
}

View File

@@ -0,0 +1,17 @@
/*
* 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 dal

View File

@@ -0,0 +1,27 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package model
const TableNameVariableInstance = "variable_instance"
// VariableInstance KV Memory
type VariableInstance struct {
ID int64 `gorm:"column:id;primaryKey;comment:主键ID" json:"id"` // 主键ID
BizType int32 `gorm:"column:biz_type;not null;comment:1 for agent2 for app" json:"biz_type"` // 1 for agent2 for app
BizID string `gorm:"column:biz_id;not null;comment:1 for agent_id2 for app_id" json:"biz_id"` // 1 for agent_id2 for app_id
Version string `gorm:"column:version;not null;comment:agent or project 版本,为空代表草稿态" json:"version"` // agent or project 版本,为空代表草稿态
Keyword string `gorm:"column:keyword;not null;comment:记忆的KEY" json:"keyword"` // 记忆的KEY
Type int32 `gorm:"column:type;not null;comment:记忆类型 1 KV 2 list" json:"type"` // 记忆类型 1 KV 2 list
Content string `gorm:"column:content;comment:记忆内容" json:"content"` // 记忆内容
ConnectorUID string `gorm:"column:connector_uid;not null;comment:二方用户ID" json:"connector_uid"` // 二方用户ID
ConnectorID int64 `gorm:"column:connector_id;not null;comment:二方id, e.g. coze = 10000010" json:"connector_id"` // 二方id, e.g. coze = 10000010
CreatedAt int64 `gorm:"column:created_at;not null;autoCreateTime:milli;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt int64 `gorm:"column:updated_at;not null;autoUpdateTime:milli;comment:更新时间" json:"updated_at"` // 更新时间
}
// TableName VariableInstance's table name
func (*VariableInstance) TableName() string {
return TableNameVariableInstance
}

View File

@@ -0,0 +1,26 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package model
import "github.com/coze-dev/coze-studio/backend/domain/memory/variables/entity"
const TableNameVariablesMeta = "variables_meta"
// VariablesMeta KV Memory meta
type VariablesMeta struct {
ID int64 `gorm:"column:id;primaryKey;comment:主键ID" json:"id"` // 主键ID
CreatorID int64 `gorm:"column:creator_id;not null;comment:创建者ID" json:"creator_id"` // 创建者ID
BizType int32 `gorm:"column:biz_type;not null;comment:1 for agent2 for app" json:"biz_type"` // 1 for agent2 for app
BizID string `gorm:"column:biz_id;not null;comment:1 for agent_id2 for app_id" json:"biz_id"` // 1 for agent_id2 for app_id
VariableList []*entity.VariableMeta `gorm:"column:variable_list;comment:变量配置的json数据;serializer:json" json:"variable_list"` // 变量配置的json数据
CreatedAt int64 `gorm:"column:created_at;not null;autoCreateTime:milli;comment:create time" json:"created_at"` // create time
UpdatedAt int64 `gorm:"column:updated_at;not null;autoUpdateTime:milli;comment:update time" json:"updated_at"` // update time
Version string `gorm:"column:version;not null;comment:project版本,为空代表草稿态" json:"version"` // project版本,为空代表草稿态
}
// TableName VariablesMeta's table name
func (*VariablesMeta) TableName() string {
return TableNameVariablesMeta
}

View File

@@ -0,0 +1,111 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package query
import (
"context"
"database/sql"
"gorm.io/gorm"
"gorm.io/gen"
"gorm.io/plugin/dbresolver"
)
var (
Q = new(Query)
VariableInstance *variableInstance
VariablesMeta *variablesMeta
)
func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
*Q = *Use(db, opts...)
VariableInstance = &Q.VariableInstance
VariablesMeta = &Q.VariablesMeta
}
func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
return &Query{
db: db,
VariableInstance: newVariableInstance(db, opts...),
VariablesMeta: newVariablesMeta(db, opts...),
}
}
type Query struct {
db *gorm.DB
VariableInstance variableInstance
VariablesMeta variablesMeta
}
func (q *Query) Available() bool { return q.db != nil }
func (q *Query) clone(db *gorm.DB) *Query {
return &Query{
db: db,
VariableInstance: q.VariableInstance.clone(db),
VariablesMeta: q.VariablesMeta.clone(db),
}
}
func (q *Query) ReadDB() *Query {
return q.ReplaceDB(q.db.Clauses(dbresolver.Read))
}
func (q *Query) WriteDB() *Query {
return q.ReplaceDB(q.db.Clauses(dbresolver.Write))
}
func (q *Query) ReplaceDB(db *gorm.DB) *Query {
return &Query{
db: db,
VariableInstance: q.VariableInstance.replaceDB(db),
VariablesMeta: q.VariablesMeta.replaceDB(db),
}
}
type queryCtx struct {
VariableInstance IVariableInstanceDo
VariablesMeta IVariablesMetaDo
}
func (q *Query) WithContext(ctx context.Context) *queryCtx {
return &queryCtx{
VariableInstance: q.VariableInstance.WithContext(ctx),
VariablesMeta: q.VariablesMeta.WithContext(ctx),
}
}
func (q *Query) Transaction(fc func(tx *Query) error, opts ...*sql.TxOptions) error {
return q.db.Transaction(func(tx *gorm.DB) error { return fc(q.clone(tx)) }, opts...)
}
func (q *Query) Begin(opts ...*sql.TxOptions) *QueryTx {
tx := q.db.Begin(opts...)
return &QueryTx{Query: q.clone(tx), Error: tx.Error}
}
type QueryTx struct {
*Query
Error error
}
func (q *QueryTx) Commit() error {
return q.db.Commit().Error
}
func (q *QueryTx) Rollback() error {
return q.db.Rollback().Error
}
func (q *QueryTx) SavePoint(name string) error {
return q.db.SavePoint(name).Error
}
func (q *QueryTx) RollbackTo(name string) error {
return q.db.RollbackTo(name).Error
}

View File

@@ -0,0 +1,421 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package query
import (
"context"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"gorm.io/gen"
"gorm.io/gen/field"
"gorm.io/plugin/dbresolver"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/internal/dal/model"
)
func newVariableInstance(db *gorm.DB, opts ...gen.DOOption) variableInstance {
_variableInstance := variableInstance{}
_variableInstance.variableInstanceDo.UseDB(db, opts...)
_variableInstance.variableInstanceDo.UseModel(&model.VariableInstance{})
tableName := _variableInstance.variableInstanceDo.TableName()
_variableInstance.ALL = field.NewAsterisk(tableName)
_variableInstance.ID = field.NewInt64(tableName, "id")
_variableInstance.BizType = field.NewInt32(tableName, "biz_type")
_variableInstance.BizID = field.NewString(tableName, "biz_id")
_variableInstance.Version = field.NewString(tableName, "version")
_variableInstance.Keyword = field.NewString(tableName, "keyword")
_variableInstance.Type = field.NewInt32(tableName, "type")
_variableInstance.Content = field.NewString(tableName, "content")
_variableInstance.ConnectorUID = field.NewString(tableName, "connector_uid")
_variableInstance.ConnectorID = field.NewInt64(tableName, "connector_id")
_variableInstance.CreatedAt = field.NewInt64(tableName, "created_at")
_variableInstance.UpdatedAt = field.NewInt64(tableName, "updated_at")
_variableInstance.fillFieldMap()
return _variableInstance
}
// variableInstance KV Memory
type variableInstance struct {
variableInstanceDo
ALL field.Asterisk
ID field.Int64 // 主键ID
BizType field.Int32 // 1 for agent2 for app
BizID field.String // 1 for agent_id2 for app_id
Version field.String // agent or project 版本,为空代表草稿态
Keyword field.String // 记忆的KEY
Type field.Int32 // 记忆类型 1 KV 2 list
Content field.String // 记忆内容
ConnectorUID field.String // 二方用户ID
ConnectorID field.Int64 // 二方id, e.g. coze = 10000010
CreatedAt field.Int64 // 创建时间
UpdatedAt field.Int64 // 更新时间
fieldMap map[string]field.Expr
}
func (v variableInstance) Table(newTableName string) *variableInstance {
v.variableInstanceDo.UseTable(newTableName)
return v.updateTableName(newTableName)
}
func (v variableInstance) As(alias string) *variableInstance {
v.variableInstanceDo.DO = *(v.variableInstanceDo.As(alias).(*gen.DO))
return v.updateTableName(alias)
}
func (v *variableInstance) updateTableName(table string) *variableInstance {
v.ALL = field.NewAsterisk(table)
v.ID = field.NewInt64(table, "id")
v.BizType = field.NewInt32(table, "biz_type")
v.BizID = field.NewString(table, "biz_id")
v.Version = field.NewString(table, "version")
v.Keyword = field.NewString(table, "keyword")
v.Type = field.NewInt32(table, "type")
v.Content = field.NewString(table, "content")
v.ConnectorUID = field.NewString(table, "connector_uid")
v.ConnectorID = field.NewInt64(table, "connector_id")
v.CreatedAt = field.NewInt64(table, "created_at")
v.UpdatedAt = field.NewInt64(table, "updated_at")
v.fillFieldMap()
return v
}
func (v *variableInstance) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
_f, ok := v.fieldMap[fieldName]
if !ok || _f == nil {
return nil, false
}
_oe, ok := _f.(field.OrderExpr)
return _oe, ok
}
func (v *variableInstance) fillFieldMap() {
v.fieldMap = make(map[string]field.Expr, 11)
v.fieldMap["id"] = v.ID
v.fieldMap["biz_type"] = v.BizType
v.fieldMap["biz_id"] = v.BizID
v.fieldMap["version"] = v.Version
v.fieldMap["keyword"] = v.Keyword
v.fieldMap["type"] = v.Type
v.fieldMap["content"] = v.Content
v.fieldMap["connector_uid"] = v.ConnectorUID
v.fieldMap["connector_id"] = v.ConnectorID
v.fieldMap["created_at"] = v.CreatedAt
v.fieldMap["updated_at"] = v.UpdatedAt
}
func (v variableInstance) clone(db *gorm.DB) variableInstance {
v.variableInstanceDo.ReplaceConnPool(db.Statement.ConnPool)
return v
}
func (v variableInstance) replaceDB(db *gorm.DB) variableInstance {
v.variableInstanceDo.ReplaceDB(db)
return v
}
type variableInstanceDo struct{ gen.DO }
type IVariableInstanceDo interface {
gen.SubQuery
Debug() IVariableInstanceDo
WithContext(ctx context.Context) IVariableInstanceDo
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
ReplaceDB(db *gorm.DB)
ReadDB() IVariableInstanceDo
WriteDB() IVariableInstanceDo
As(alias string) gen.Dao
Session(config *gorm.Session) IVariableInstanceDo
Columns(cols ...field.Expr) gen.Columns
Clauses(conds ...clause.Expression) IVariableInstanceDo
Not(conds ...gen.Condition) IVariableInstanceDo
Or(conds ...gen.Condition) IVariableInstanceDo
Select(conds ...field.Expr) IVariableInstanceDo
Where(conds ...gen.Condition) IVariableInstanceDo
Order(conds ...field.Expr) IVariableInstanceDo
Distinct(cols ...field.Expr) IVariableInstanceDo
Omit(cols ...field.Expr) IVariableInstanceDo
Join(table schema.Tabler, on ...field.Expr) IVariableInstanceDo
LeftJoin(table schema.Tabler, on ...field.Expr) IVariableInstanceDo
RightJoin(table schema.Tabler, on ...field.Expr) IVariableInstanceDo
Group(cols ...field.Expr) IVariableInstanceDo
Having(conds ...gen.Condition) IVariableInstanceDo
Limit(limit int) IVariableInstanceDo
Offset(offset int) IVariableInstanceDo
Count() (count int64, err error)
Scopes(funcs ...func(gen.Dao) gen.Dao) IVariableInstanceDo
Unscoped() IVariableInstanceDo
Create(values ...*model.VariableInstance) error
CreateInBatches(values []*model.VariableInstance, batchSize int) error
Save(values ...*model.VariableInstance) error
First() (*model.VariableInstance, error)
Take() (*model.VariableInstance, error)
Last() (*model.VariableInstance, error)
Find() ([]*model.VariableInstance, error)
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.VariableInstance, err error)
FindInBatches(result *[]*model.VariableInstance, batchSize int, fc func(tx gen.Dao, batch int) error) error
Pluck(column field.Expr, dest interface{}) error
Delete(...*model.VariableInstance) (info gen.ResultInfo, err error)
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
Updates(value interface{}) (info gen.ResultInfo, err error)
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
UpdateFrom(q gen.SubQuery) gen.Dao
Attrs(attrs ...field.AssignExpr) IVariableInstanceDo
Assign(attrs ...field.AssignExpr) IVariableInstanceDo
Joins(fields ...field.RelationField) IVariableInstanceDo
Preload(fields ...field.RelationField) IVariableInstanceDo
FirstOrInit() (*model.VariableInstance, error)
FirstOrCreate() (*model.VariableInstance, error)
FindByPage(offset int, limit int) (result []*model.VariableInstance, count int64, err error)
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
Scan(result interface{}) (err error)
Returning(value interface{}, columns ...string) IVariableInstanceDo
UnderlyingDB() *gorm.DB
schema.Tabler
}
func (v variableInstanceDo) Debug() IVariableInstanceDo {
return v.withDO(v.DO.Debug())
}
func (v variableInstanceDo) WithContext(ctx context.Context) IVariableInstanceDo {
return v.withDO(v.DO.WithContext(ctx))
}
func (v variableInstanceDo) ReadDB() IVariableInstanceDo {
return v.Clauses(dbresolver.Read)
}
func (v variableInstanceDo) WriteDB() IVariableInstanceDo {
return v.Clauses(dbresolver.Write)
}
func (v variableInstanceDo) Session(config *gorm.Session) IVariableInstanceDo {
return v.withDO(v.DO.Session(config))
}
func (v variableInstanceDo) Clauses(conds ...clause.Expression) IVariableInstanceDo {
return v.withDO(v.DO.Clauses(conds...))
}
func (v variableInstanceDo) Returning(value interface{}, columns ...string) IVariableInstanceDo {
return v.withDO(v.DO.Returning(value, columns...))
}
func (v variableInstanceDo) Not(conds ...gen.Condition) IVariableInstanceDo {
return v.withDO(v.DO.Not(conds...))
}
func (v variableInstanceDo) Or(conds ...gen.Condition) IVariableInstanceDo {
return v.withDO(v.DO.Or(conds...))
}
func (v variableInstanceDo) Select(conds ...field.Expr) IVariableInstanceDo {
return v.withDO(v.DO.Select(conds...))
}
func (v variableInstanceDo) Where(conds ...gen.Condition) IVariableInstanceDo {
return v.withDO(v.DO.Where(conds...))
}
func (v variableInstanceDo) Order(conds ...field.Expr) IVariableInstanceDo {
return v.withDO(v.DO.Order(conds...))
}
func (v variableInstanceDo) Distinct(cols ...field.Expr) IVariableInstanceDo {
return v.withDO(v.DO.Distinct(cols...))
}
func (v variableInstanceDo) Omit(cols ...field.Expr) IVariableInstanceDo {
return v.withDO(v.DO.Omit(cols...))
}
func (v variableInstanceDo) Join(table schema.Tabler, on ...field.Expr) IVariableInstanceDo {
return v.withDO(v.DO.Join(table, on...))
}
func (v variableInstanceDo) LeftJoin(table schema.Tabler, on ...field.Expr) IVariableInstanceDo {
return v.withDO(v.DO.LeftJoin(table, on...))
}
func (v variableInstanceDo) RightJoin(table schema.Tabler, on ...field.Expr) IVariableInstanceDo {
return v.withDO(v.DO.RightJoin(table, on...))
}
func (v variableInstanceDo) Group(cols ...field.Expr) IVariableInstanceDo {
return v.withDO(v.DO.Group(cols...))
}
func (v variableInstanceDo) Having(conds ...gen.Condition) IVariableInstanceDo {
return v.withDO(v.DO.Having(conds...))
}
func (v variableInstanceDo) Limit(limit int) IVariableInstanceDo {
return v.withDO(v.DO.Limit(limit))
}
func (v variableInstanceDo) Offset(offset int) IVariableInstanceDo {
return v.withDO(v.DO.Offset(offset))
}
func (v variableInstanceDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IVariableInstanceDo {
return v.withDO(v.DO.Scopes(funcs...))
}
func (v variableInstanceDo) Unscoped() IVariableInstanceDo {
return v.withDO(v.DO.Unscoped())
}
func (v variableInstanceDo) Create(values ...*model.VariableInstance) error {
if len(values) == 0 {
return nil
}
return v.DO.Create(values)
}
func (v variableInstanceDo) CreateInBatches(values []*model.VariableInstance, batchSize int) error {
return v.DO.CreateInBatches(values, batchSize)
}
// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (v variableInstanceDo) Save(values ...*model.VariableInstance) error {
if len(values) == 0 {
return nil
}
return v.DO.Save(values)
}
func (v variableInstanceDo) First() (*model.VariableInstance, error) {
if result, err := v.DO.First(); err != nil {
return nil, err
} else {
return result.(*model.VariableInstance), nil
}
}
func (v variableInstanceDo) Take() (*model.VariableInstance, error) {
if result, err := v.DO.Take(); err != nil {
return nil, err
} else {
return result.(*model.VariableInstance), nil
}
}
func (v variableInstanceDo) Last() (*model.VariableInstance, error) {
if result, err := v.DO.Last(); err != nil {
return nil, err
} else {
return result.(*model.VariableInstance), nil
}
}
func (v variableInstanceDo) Find() ([]*model.VariableInstance, error) {
result, err := v.DO.Find()
return result.([]*model.VariableInstance), err
}
func (v variableInstanceDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.VariableInstance, err error) {
buf := make([]*model.VariableInstance, 0, batchSize)
err = v.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
defer func() { results = append(results, buf...) }()
return fc(tx, batch)
})
return results, err
}
func (v variableInstanceDo) FindInBatches(result *[]*model.VariableInstance, batchSize int, fc func(tx gen.Dao, batch int) error) error {
return v.DO.FindInBatches(result, batchSize, fc)
}
func (v variableInstanceDo) Attrs(attrs ...field.AssignExpr) IVariableInstanceDo {
return v.withDO(v.DO.Attrs(attrs...))
}
func (v variableInstanceDo) Assign(attrs ...field.AssignExpr) IVariableInstanceDo {
return v.withDO(v.DO.Assign(attrs...))
}
func (v variableInstanceDo) Joins(fields ...field.RelationField) IVariableInstanceDo {
for _, _f := range fields {
v = *v.withDO(v.DO.Joins(_f))
}
return &v
}
func (v variableInstanceDo) Preload(fields ...field.RelationField) IVariableInstanceDo {
for _, _f := range fields {
v = *v.withDO(v.DO.Preload(_f))
}
return &v
}
func (v variableInstanceDo) FirstOrInit() (*model.VariableInstance, error) {
if result, err := v.DO.FirstOrInit(); err != nil {
return nil, err
} else {
return result.(*model.VariableInstance), nil
}
}
func (v variableInstanceDo) FirstOrCreate() (*model.VariableInstance, error) {
if result, err := v.DO.FirstOrCreate(); err != nil {
return nil, err
} else {
return result.(*model.VariableInstance), nil
}
}
func (v variableInstanceDo) FindByPage(offset int, limit int) (result []*model.VariableInstance, count int64, err error) {
result, err = v.Offset(offset).Limit(limit).Find()
if err != nil {
return
}
if size := len(result); 0 < limit && 0 < size && size < limit {
count = int64(size + offset)
return
}
count, err = v.Offset(-1).Limit(-1).Count()
return
}
func (v variableInstanceDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
count, err = v.Count()
if err != nil {
return
}
err = v.Offset(offset).Limit(limit).Scan(result)
return
}
func (v variableInstanceDo) Scan(result interface{}) (err error) {
return v.DO.Scan(result)
}
func (v variableInstanceDo) Delete(models ...*model.VariableInstance) (result gen.ResultInfo, err error) {
return v.DO.Delete(models)
}
func (v *variableInstanceDo) withDO(do gen.Dao) *variableInstanceDo {
v.DO = *do.(*gen.DO)
return v
}

View File

@@ -0,0 +1,409 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package query
import (
"context"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"gorm.io/gen"
"gorm.io/gen/field"
"gorm.io/plugin/dbresolver"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/internal/dal/model"
)
func newVariablesMeta(db *gorm.DB, opts ...gen.DOOption) variablesMeta {
_variablesMeta := variablesMeta{}
_variablesMeta.variablesMetaDo.UseDB(db, opts...)
_variablesMeta.variablesMetaDo.UseModel(&model.VariablesMeta{})
tableName := _variablesMeta.variablesMetaDo.TableName()
_variablesMeta.ALL = field.NewAsterisk(tableName)
_variablesMeta.ID = field.NewInt64(tableName, "id")
_variablesMeta.CreatorID = field.NewInt64(tableName, "creator_id")
_variablesMeta.BizType = field.NewInt32(tableName, "biz_type")
_variablesMeta.BizID = field.NewString(tableName, "biz_id")
_variablesMeta.VariableList = field.NewField(tableName, "variable_list")
_variablesMeta.CreatedAt = field.NewInt64(tableName, "created_at")
_variablesMeta.UpdatedAt = field.NewInt64(tableName, "updated_at")
_variablesMeta.Version = field.NewString(tableName, "version")
_variablesMeta.fillFieldMap()
return _variablesMeta
}
// variablesMeta KV Memory meta
type variablesMeta struct {
variablesMetaDo
ALL field.Asterisk
ID field.Int64 // 主键ID
CreatorID field.Int64 // 创建者ID
BizType field.Int32 // 1 for agent2 for app
BizID field.String // 1 for agent_id2 for app_id
VariableList field.Field // 变量配置的json数据
CreatedAt field.Int64 // create time
UpdatedAt field.Int64 // update time
Version field.String // project版本,为空代表草稿态
fieldMap map[string]field.Expr
}
func (v variablesMeta) Table(newTableName string) *variablesMeta {
v.variablesMetaDo.UseTable(newTableName)
return v.updateTableName(newTableName)
}
func (v variablesMeta) As(alias string) *variablesMeta {
v.variablesMetaDo.DO = *(v.variablesMetaDo.As(alias).(*gen.DO))
return v.updateTableName(alias)
}
func (v *variablesMeta) updateTableName(table string) *variablesMeta {
v.ALL = field.NewAsterisk(table)
v.ID = field.NewInt64(table, "id")
v.CreatorID = field.NewInt64(table, "creator_id")
v.BizType = field.NewInt32(table, "biz_type")
v.BizID = field.NewString(table, "biz_id")
v.VariableList = field.NewField(table, "variable_list")
v.CreatedAt = field.NewInt64(table, "created_at")
v.UpdatedAt = field.NewInt64(table, "updated_at")
v.Version = field.NewString(table, "version")
v.fillFieldMap()
return v
}
func (v *variablesMeta) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
_f, ok := v.fieldMap[fieldName]
if !ok || _f == nil {
return nil, false
}
_oe, ok := _f.(field.OrderExpr)
return _oe, ok
}
func (v *variablesMeta) fillFieldMap() {
v.fieldMap = make(map[string]field.Expr, 8)
v.fieldMap["id"] = v.ID
v.fieldMap["creator_id"] = v.CreatorID
v.fieldMap["biz_type"] = v.BizType
v.fieldMap["biz_id"] = v.BizID
v.fieldMap["variable_list"] = v.VariableList
v.fieldMap["created_at"] = v.CreatedAt
v.fieldMap["updated_at"] = v.UpdatedAt
v.fieldMap["version"] = v.Version
}
func (v variablesMeta) clone(db *gorm.DB) variablesMeta {
v.variablesMetaDo.ReplaceConnPool(db.Statement.ConnPool)
return v
}
func (v variablesMeta) replaceDB(db *gorm.DB) variablesMeta {
v.variablesMetaDo.ReplaceDB(db)
return v
}
type variablesMetaDo struct{ gen.DO }
type IVariablesMetaDo interface {
gen.SubQuery
Debug() IVariablesMetaDo
WithContext(ctx context.Context) IVariablesMetaDo
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
ReplaceDB(db *gorm.DB)
ReadDB() IVariablesMetaDo
WriteDB() IVariablesMetaDo
As(alias string) gen.Dao
Session(config *gorm.Session) IVariablesMetaDo
Columns(cols ...field.Expr) gen.Columns
Clauses(conds ...clause.Expression) IVariablesMetaDo
Not(conds ...gen.Condition) IVariablesMetaDo
Or(conds ...gen.Condition) IVariablesMetaDo
Select(conds ...field.Expr) IVariablesMetaDo
Where(conds ...gen.Condition) IVariablesMetaDo
Order(conds ...field.Expr) IVariablesMetaDo
Distinct(cols ...field.Expr) IVariablesMetaDo
Omit(cols ...field.Expr) IVariablesMetaDo
Join(table schema.Tabler, on ...field.Expr) IVariablesMetaDo
LeftJoin(table schema.Tabler, on ...field.Expr) IVariablesMetaDo
RightJoin(table schema.Tabler, on ...field.Expr) IVariablesMetaDo
Group(cols ...field.Expr) IVariablesMetaDo
Having(conds ...gen.Condition) IVariablesMetaDo
Limit(limit int) IVariablesMetaDo
Offset(offset int) IVariablesMetaDo
Count() (count int64, err error)
Scopes(funcs ...func(gen.Dao) gen.Dao) IVariablesMetaDo
Unscoped() IVariablesMetaDo
Create(values ...*model.VariablesMeta) error
CreateInBatches(values []*model.VariablesMeta, batchSize int) error
Save(values ...*model.VariablesMeta) error
First() (*model.VariablesMeta, error)
Take() (*model.VariablesMeta, error)
Last() (*model.VariablesMeta, error)
Find() ([]*model.VariablesMeta, error)
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.VariablesMeta, err error)
FindInBatches(result *[]*model.VariablesMeta, batchSize int, fc func(tx gen.Dao, batch int) error) error
Pluck(column field.Expr, dest interface{}) error
Delete(...*model.VariablesMeta) (info gen.ResultInfo, err error)
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
Updates(value interface{}) (info gen.ResultInfo, err error)
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
UpdateFrom(q gen.SubQuery) gen.Dao
Attrs(attrs ...field.AssignExpr) IVariablesMetaDo
Assign(attrs ...field.AssignExpr) IVariablesMetaDo
Joins(fields ...field.RelationField) IVariablesMetaDo
Preload(fields ...field.RelationField) IVariablesMetaDo
FirstOrInit() (*model.VariablesMeta, error)
FirstOrCreate() (*model.VariablesMeta, error)
FindByPage(offset int, limit int) (result []*model.VariablesMeta, count int64, err error)
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
Scan(result interface{}) (err error)
Returning(value interface{}, columns ...string) IVariablesMetaDo
UnderlyingDB() *gorm.DB
schema.Tabler
}
func (v variablesMetaDo) Debug() IVariablesMetaDo {
return v.withDO(v.DO.Debug())
}
func (v variablesMetaDo) WithContext(ctx context.Context) IVariablesMetaDo {
return v.withDO(v.DO.WithContext(ctx))
}
func (v variablesMetaDo) ReadDB() IVariablesMetaDo {
return v.Clauses(dbresolver.Read)
}
func (v variablesMetaDo) WriteDB() IVariablesMetaDo {
return v.Clauses(dbresolver.Write)
}
func (v variablesMetaDo) Session(config *gorm.Session) IVariablesMetaDo {
return v.withDO(v.DO.Session(config))
}
func (v variablesMetaDo) Clauses(conds ...clause.Expression) IVariablesMetaDo {
return v.withDO(v.DO.Clauses(conds...))
}
func (v variablesMetaDo) Returning(value interface{}, columns ...string) IVariablesMetaDo {
return v.withDO(v.DO.Returning(value, columns...))
}
func (v variablesMetaDo) Not(conds ...gen.Condition) IVariablesMetaDo {
return v.withDO(v.DO.Not(conds...))
}
func (v variablesMetaDo) Or(conds ...gen.Condition) IVariablesMetaDo {
return v.withDO(v.DO.Or(conds...))
}
func (v variablesMetaDo) Select(conds ...field.Expr) IVariablesMetaDo {
return v.withDO(v.DO.Select(conds...))
}
func (v variablesMetaDo) Where(conds ...gen.Condition) IVariablesMetaDo {
return v.withDO(v.DO.Where(conds...))
}
func (v variablesMetaDo) Order(conds ...field.Expr) IVariablesMetaDo {
return v.withDO(v.DO.Order(conds...))
}
func (v variablesMetaDo) Distinct(cols ...field.Expr) IVariablesMetaDo {
return v.withDO(v.DO.Distinct(cols...))
}
func (v variablesMetaDo) Omit(cols ...field.Expr) IVariablesMetaDo {
return v.withDO(v.DO.Omit(cols...))
}
func (v variablesMetaDo) Join(table schema.Tabler, on ...field.Expr) IVariablesMetaDo {
return v.withDO(v.DO.Join(table, on...))
}
func (v variablesMetaDo) LeftJoin(table schema.Tabler, on ...field.Expr) IVariablesMetaDo {
return v.withDO(v.DO.LeftJoin(table, on...))
}
func (v variablesMetaDo) RightJoin(table schema.Tabler, on ...field.Expr) IVariablesMetaDo {
return v.withDO(v.DO.RightJoin(table, on...))
}
func (v variablesMetaDo) Group(cols ...field.Expr) IVariablesMetaDo {
return v.withDO(v.DO.Group(cols...))
}
func (v variablesMetaDo) Having(conds ...gen.Condition) IVariablesMetaDo {
return v.withDO(v.DO.Having(conds...))
}
func (v variablesMetaDo) Limit(limit int) IVariablesMetaDo {
return v.withDO(v.DO.Limit(limit))
}
func (v variablesMetaDo) Offset(offset int) IVariablesMetaDo {
return v.withDO(v.DO.Offset(offset))
}
func (v variablesMetaDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IVariablesMetaDo {
return v.withDO(v.DO.Scopes(funcs...))
}
func (v variablesMetaDo) Unscoped() IVariablesMetaDo {
return v.withDO(v.DO.Unscoped())
}
func (v variablesMetaDo) Create(values ...*model.VariablesMeta) error {
if len(values) == 0 {
return nil
}
return v.DO.Create(values)
}
func (v variablesMetaDo) CreateInBatches(values []*model.VariablesMeta, batchSize int) error {
return v.DO.CreateInBatches(values, batchSize)
}
// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (v variablesMetaDo) Save(values ...*model.VariablesMeta) error {
if len(values) == 0 {
return nil
}
return v.DO.Save(values)
}
func (v variablesMetaDo) First() (*model.VariablesMeta, error) {
if result, err := v.DO.First(); err != nil {
return nil, err
} else {
return result.(*model.VariablesMeta), nil
}
}
func (v variablesMetaDo) Take() (*model.VariablesMeta, error) {
if result, err := v.DO.Take(); err != nil {
return nil, err
} else {
return result.(*model.VariablesMeta), nil
}
}
func (v variablesMetaDo) Last() (*model.VariablesMeta, error) {
if result, err := v.DO.Last(); err != nil {
return nil, err
} else {
return result.(*model.VariablesMeta), nil
}
}
func (v variablesMetaDo) Find() ([]*model.VariablesMeta, error) {
result, err := v.DO.Find()
return result.([]*model.VariablesMeta), err
}
func (v variablesMetaDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.VariablesMeta, err error) {
buf := make([]*model.VariablesMeta, 0, batchSize)
err = v.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
defer func() { results = append(results, buf...) }()
return fc(tx, batch)
})
return results, err
}
func (v variablesMetaDo) FindInBatches(result *[]*model.VariablesMeta, batchSize int, fc func(tx gen.Dao, batch int) error) error {
return v.DO.FindInBatches(result, batchSize, fc)
}
func (v variablesMetaDo) Attrs(attrs ...field.AssignExpr) IVariablesMetaDo {
return v.withDO(v.DO.Attrs(attrs...))
}
func (v variablesMetaDo) Assign(attrs ...field.AssignExpr) IVariablesMetaDo {
return v.withDO(v.DO.Assign(attrs...))
}
func (v variablesMetaDo) Joins(fields ...field.RelationField) IVariablesMetaDo {
for _, _f := range fields {
v = *v.withDO(v.DO.Joins(_f))
}
return &v
}
func (v variablesMetaDo) Preload(fields ...field.RelationField) IVariablesMetaDo {
for _, _f := range fields {
v = *v.withDO(v.DO.Preload(_f))
}
return &v
}
func (v variablesMetaDo) FirstOrInit() (*model.VariablesMeta, error) {
if result, err := v.DO.FirstOrInit(); err != nil {
return nil, err
} else {
return result.(*model.VariablesMeta), nil
}
}
func (v variablesMetaDo) FirstOrCreate() (*model.VariablesMeta, error) {
if result, err := v.DO.FirstOrCreate(); err != nil {
return nil, err
} else {
return result.(*model.VariablesMeta), nil
}
}
func (v variablesMetaDo) FindByPage(offset int, limit int) (result []*model.VariablesMeta, count int64, err error) {
result, err = v.Offset(offset).Limit(limit).Find()
if err != nil {
return
}
if size := len(result); 0 < limit && 0 < size && size < limit {
count = int64(size + offset)
return
}
count, err = v.Offset(-1).Limit(-1).Count()
return
}
func (v variablesMetaDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
count, err = v.Count()
if err != nil {
return
}
err = v.Offset(offset).Limit(limit).Scan(result)
return
}
func (v variablesMetaDo) Scan(result interface{}) (err error) {
return v.DO.Scan(result)
}
func (v variablesMetaDo) Delete(models ...*model.VariablesMeta) (result gen.ResultInfo, err error) {
return v.DO.Delete(models)
}
func (v *variablesMetaDo) withDO(do gen.Dao) *variablesMetaDo {
v.DO = *do.(*gen.DO)
return v
}

View File

@@ -0,0 +1,212 @@
/*
* 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 dal
import (
"context"
"gorm.io/gen"
"gorm.io/gorm"
"github.com/coze-dev/coze-studio/backend/api/model/project_memory"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/entity"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/internal/dal/model"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/internal/dal/query"
"github.com/coze-dev/coze-studio/backend/infra/contract/idgen"
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
"github.com/coze-dev/coze-studio/backend/types/errno"
)
type VariablesDAO struct {
IDGen idgen.IDGenerator
}
func NewDAO(db *gorm.DB, generator idgen.IDGenerator) *VariablesDAO {
query.SetDefault(db)
return &VariablesDAO{
IDGen: generator,
}
}
func (v *VariablesDAO) DeleteAllVariableData(ctx context.Context, bizType project_memory.VariableConnector, bizID string) (err error) {
tx := query.Q.Begin()
if tx.Error != nil {
return tx.Error
}
defer func() {
if err != nil {
tx.Rollback()
}
}()
varInstanceTable := tx.VariableInstance
varInsWhere := []gen.Condition{
varInstanceTable.BizType.Eq(int32(bizType)),
varInstanceTable.BizID.Eq(bizID),
}
_, err = varInstanceTable.WithContext(ctx).Where(varInsWhere...).Delete()
if err != nil {
return tx.Error
}
varMetaTable := tx.VariablesMeta
varMetaWhere := []gen.Condition{
varMetaTable.BizType.Eq(int32(bizType)),
varMetaTable.BizID.Eq(bizID),
}
_, err = varMetaTable.WithContext(ctx).Where(varMetaWhere...).Delete()
if err != nil {
return tx.Error
}
err = tx.Commit()
return err
}
func (v *VariablesDAO) DeleteVariableInstance(ctx context.Context, do *entity.UserVariableMeta, keywords []string) error {
table := query.VariableInstance
condWhere := []gen.Condition{
table.BizType.Eq(int32(do.BizType)),
table.BizID.Eq(do.BizID),
table.Version.Eq(do.Version),
table.ConnectorUID.Eq(do.ConnectorUID),
table.ConnectorID.Eq(do.ConnectorID),
}
if len(keywords) > 0 {
condWhere = append(condWhere, table.Keyword.In(keywords...))
}
_, err := table.WithContext(ctx).Where(condWhere...).Delete(&model.VariableInstance{})
if err != nil {
return errorx.WrapByCode(err, errno.ErrMemoryDeleteVariableInstanceCode)
}
return nil
}
func (v *VariablesDAO) GetVariableInstances(ctx context.Context, do *entity.UserVariableMeta, keywords []string) ([]*entity.VariableInstance, error) {
table := query.VariableInstance
condWhere := []gen.Condition{
table.BizType.Eq(int32(do.BizType)),
table.BizID.Eq(do.BizID),
table.Version.Eq(do.Version),
table.ConnectorUID.Eq(do.ConnectorUID),
table.ConnectorID.Eq(do.ConnectorID),
}
if len(keywords) > 0 {
condWhere = append(condWhere, table.Keyword.In(keywords...))
}
res, err := table.WithContext(ctx).Where(condWhere...).Find()
if err != nil {
return nil, errorx.WrapByCode(err, errno.ErrMemoryGetVariableInstanceCode)
}
dos := make([]*entity.VariableInstance, 0, len(res))
for _, vv := range res {
dos = append(dos, v.variableInstanceToDO(vv))
}
return dos, nil
}
func (v *VariablesDAO) variableInstanceToDO(po *model.VariableInstance) *entity.VariableInstance {
return &entity.VariableInstance{
ID: po.ID,
BizType: project_memory.VariableConnector(po.BizType),
BizID: po.BizID,
Version: po.Version,
ConnectorUID: po.ConnectorUID,
ConnectorID: po.ConnectorID,
Keyword: po.Keyword,
Type: po.Type,
Content: po.Content,
CreatedAt: po.CreatedAt,
UpdatedAt: po.UpdatedAt,
}
}
func (v *VariablesDAO) variableInstanceToPO(po *entity.VariableInstance) *model.VariableInstance {
return &model.VariableInstance{
ID: po.ID,
BizType: int32(po.BizType),
BizID: po.BizID,
Version: po.Version,
ConnectorUID: po.ConnectorUID,
ConnectorID: po.ConnectorID,
Keyword: po.Keyword,
Type: po.Type,
Content: po.Content,
CreatedAt: po.CreatedAt,
UpdatedAt: po.UpdatedAt,
}
}
func (m *VariablesDAO) UpdateVariableInstance(ctx context.Context, KVs []*entity.VariableInstance) error {
if len(KVs) == 0 {
return nil
}
table := query.VariableInstance
for _, v := range KVs {
p := m.variableInstanceToPO(v)
_, err := table.WithContext(ctx).
Where(
table.ID.Eq(p.ID),
).
Updates(p)
if err != nil {
return errorx.WrapByCode(err, errno.ErrMemoryUpdateVariableInstanceCode)
}
}
return nil
}
func (m *VariablesDAO) InsertVariableInstance(ctx context.Context, KVs []*entity.VariableInstance) error {
if len(KVs) == 0 {
return nil
}
table := query.VariableInstance
ids, err := m.IDGen.GenMultiIDs(ctx, len(KVs))
if err != nil {
return errorx.WrapByCode(err, errno.ErrMemoryIDGenFailCode, errorx.KV("msg", "InsertVariableInstance"))
}
pos := make([]*model.VariableInstance, 0, len(KVs))
for i, v := range KVs {
p := m.variableInstanceToPO(v)
p.ID = ids[i]
pos = append(pos, p)
}
err = table.WithContext(ctx).CreateInBatches(pos, 10)
if err != nil {
return errorx.WrapByCode(err, errno.ErrMemoryInsertVariableInstanceCode)
}
return nil
}

View File

@@ -0,0 +1,159 @@
/*
* 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 dal
import (
"context"
"errors"
"gorm.io/gen"
"gorm.io/gorm"
"github.com/coze-dev/coze-studio/backend/api/model/project_memory"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/entity"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/internal/dal/model"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/internal/dal/query"
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
"github.com/coze-dev/coze-studio/backend/types/errno"
)
func (m *VariablesDAO) GetProjectVariable(ctx context.Context, projectID, version string) (*entity.VariablesMeta, error) {
return m.GetVariableMeta(ctx, projectID, project_memory.VariableConnector_Project, version)
}
func (m *VariablesDAO) GetAgentVariable(ctx context.Context, projectID, version string) (*entity.VariablesMeta, error) {
return m.GetVariableMeta(ctx, projectID, project_memory.VariableConnector_Bot, version)
}
func (m *VariablesDAO) CreateProjectVariable(ctx context.Context, do *entity.VariablesMeta) (int64, error) {
return m.CreateVariableMeta(ctx, do, project_memory.VariableConnector_Project)
}
func (m *VariablesDAO) CreateVariableMeta(ctx context.Context, do *entity.VariablesMeta, bizType project_memory.VariableConnector) (int64, error) {
table := query.VariablesMeta
id, err := m.IDGen.GenID(ctx)
if err != nil {
return 0, errorx.WrapByCode(err, errno.ErrMemoryIDGenFailCode, errorx.KV("msg", "CreateProjectVariable"))
}
po := m.variablesMetaDO2PO(do)
po.ID = id
po.BizType = int32(bizType)
err = table.WithContext(ctx).Create(po)
if err != nil {
return 0, errorx.WrapByCode(err, errno.ErrMemoryCreateAppVariableCode)
}
return id, nil
}
func (m *VariablesDAO) UpdateProjectVariable(ctx context.Context, do *entity.VariablesMeta, bizType project_memory.VariableConnector) error {
table := query.VariablesMeta
condWhere := []gen.Condition{
table.ID.Eq(do.ID),
table.BizType.Eq(int32(bizType)),
}
po := m.variablesMetaDO2PO(do)
_, err := table.WithContext(ctx).Where(condWhere...).Updates(po)
if err != nil {
return errorx.WrapByCode(err, errno.ErrMemoryUpdateAppVariableCode)
}
return nil
}
// GetVariableMeta 获取变量元数据 , 不存在返回 nil
func (m *VariablesDAO) GetVariableMeta(ctx context.Context, bizID string, bizType project_memory.VariableConnector, version string) (*entity.VariablesMeta, error) {
table := query.VariablesMeta
condWhere := []gen.Condition{
table.BizID.Eq(bizID),
table.BizType.Eq(int32(bizType)),
table.Version.Eq(version),
}
data, err := table.WithContext(ctx).Where(condWhere...).First()
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
if err != nil {
return nil, errorx.WrapByCode(err, errno.ErrMemoryGetVariableMetaCode)
}
do := m.variablesMetaPO2DO(data)
return do, nil
}
// GetVariableMetaByID 获取变量元数据, 不存在返回 nil
func (m *VariablesDAO) GetVariableMetaByID(ctx context.Context, id int64) (*entity.VariablesMeta, error) {
table := query.VariablesMeta
condWhere := []gen.Condition{
table.ID.Eq(id),
}
data, err := table.WithContext(ctx).Where(condWhere...).First()
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
if err != nil {
return nil, errorx.WrapByCode(err, errno.ErrMemoryGetVariableMetaCode)
}
do := m.variablesMetaPO2DO(data)
return do, nil
}
func (m *VariablesDAO) variablesMetaPO2DO(po *model.VariablesMeta) *entity.VariablesMeta {
if po == nil {
return nil
}
return &entity.VariablesMeta{
ID: po.ID,
CreatorID: po.CreatorID,
BizType: project_memory.VariableConnector(po.BizType),
BizID: po.BizID,
Variables: po.VariableList,
CreatedAt: po.CreatedAt,
UpdatedAt: po.UpdatedAt,
Version: po.Version,
}
}
func (m *VariablesDAO) variablesMetaDO2PO(do *entity.VariablesMeta) *model.VariablesMeta {
if do == nil {
return nil
}
return &model.VariablesMeta{
ID: do.ID,
CreatorID: do.CreatorID,
BizType: int32(do.BizType),
BizID: do.BizID,
VariableList: do.Variables,
CreatedAt: do.CreatedAt,
UpdatedAt: do.UpdatedAt,
Version: do.Version,
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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 repository
import (
"context"
"gorm.io/gorm"
"github.com/coze-dev/coze-studio/backend/api/model/project_memory"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/entity"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/internal/dal"
"github.com/coze-dev/coze-studio/backend/infra/contract/idgen"
)
func NewVariableRepo(db *gorm.DB, generator idgen.IDGenerator) VariableRepository {
return dal.NewDAO(db, generator)
}
type VariableRepository interface {
DeleteAllVariableData(ctx context.Context, bizType project_memory.VariableConnector, bizID string) (err error)
DeleteVariableInstance(ctx context.Context, do *entity.UserVariableMeta, keywords []string) error
GetVariableInstances(ctx context.Context, do *entity.UserVariableMeta, keywords []string) ([]*entity.VariableInstance, error)
UpdateVariableInstance(ctx context.Context, KVs []*entity.VariableInstance) error
InsertVariableInstance(ctx context.Context, KVs []*entity.VariableInstance) error
GetProjectVariable(ctx context.Context, projectID, version string) (*entity.VariablesMeta, error)
GetAgentVariable(ctx context.Context, projectID, version string) (*entity.VariablesMeta, error)
CreateProjectVariable(ctx context.Context, do *entity.VariablesMeta) (int64, error)
CreateVariableMeta(ctx context.Context, do *entity.VariablesMeta, bizType project_memory.VariableConnector) (int64, error)
UpdateProjectVariable(ctx context.Context, do *entity.VariablesMeta, bizType project_memory.VariableConnector) error
GetVariableMeta(ctx context.Context, bizID string, bizType project_memory.VariableConnector, version string) (*entity.VariablesMeta, error)
GetVariableMetaByID(ctx context.Context, id int64) (*entity.VariablesMeta, error)
}

View File

@@ -0,0 +1,45 @@
/*
* 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"
"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/domain/memory/variables/entity"
)
type Variables interface {
GetVariableMeta(ctx context.Context, bizID string, bizType project_memory.VariableConnector, version string) (*entity.VariablesMeta, error)
GetVariableMetaByID(ctx context.Context, id int64) (*entity.VariablesMeta, error)
GetAgentVariableMeta(ctx context.Context, agentID int64, version string) (*entity.VariablesMeta, error)
GetProjectVariablesMeta(ctx context.Context, projectID, version string) (*entity.VariablesMeta, error)
GetSysVariableConf(ctx context.Context) entity.SysConfVariables
UpsertMeta(ctx context.Context, e *entity.VariablesMeta) (int64, error)
UpsertProjectMeta(ctx context.Context, projectID, version string, userID int64, e *entity.VariablesMeta) (int64, error)
UpsertBotMeta(ctx context.Context, agentID int64, version string, userID int64, e *entity.VariablesMeta) (int64, error)
PublishMeta(ctx context.Context, variableMetaID int64, version string) (int64, error)
SetVariableInstance(ctx context.Context, e *entity.UserVariableMeta, items []*kvmemory.KVItem) ([]string, error)
GetVariableInstance(ctx context.Context, e *entity.UserVariableMeta, keywords []string) ([]*kvmemory.KVItem, error)
GetVariableChannelInstance(ctx context.Context, e *entity.UserVariableMeta, keywords []string, varChannel *project_memory.VariableChannel) ([]*kvmemory.KVItem, error)
DeleteVariableInstance(ctx context.Context, e *entity.UserVariableMeta, keywords []string) error
DeleteAllVariable(ctx context.Context, bizType project_memory.VariableConnector, bizID string) (err error)
DecryptSysUUIDKey(ctx context.Context, encryptSysUUIDKey string) *entity.VariableInstance
}

View File

@@ -0,0 +1,543 @@
/*
* 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"
"time"
"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/domain/memory/variables/entity"
"github.com/coze-dev/coze-studio/backend/domain/memory/variables/repository"
"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/types/errno"
)
var sysVariableConf []*kvmemory.VariableInfo = []*kvmemory.VariableInfo{
{
Key: "sys_uuid",
Description: "用户唯一ID",
DefaultValue: "",
Example: "",
ExtDesc: "",
GroupDesc: "用户请求/授权后系统自动获取的相关数据",
GroupExtDesc: "",
GroupName: "用户信息",
Sensitive: "false",
CanWrite: "false",
MustNotUseInPrompt: "false",
EffectiveChannelList: []string{"全渠道"},
},
}
var sysVariableConfEN []*kvmemory.VariableInfo = []*kvmemory.VariableInfo{
{
Key: "sys_uuid",
Description: "User uniq ID",
DefaultValue: "",
Example: "",
ExtDesc: "",
GroupDesc: "Data automatically retrieved by the system after user request or authorization.",
GroupExtDesc: "",
GroupName: "User information",
Sensitive: "false",
CanWrite: "false",
MustNotUseInPrompt: "false",
EffectiveChannelList: []string{"All publication channels"},
},
}
type variablesImpl struct {
Repo repository.VariableRepository
}
func NewService(repo repository.VariableRepository) Variables {
return &variablesImpl{
Repo: repo,
}
}
func (v *variablesImpl) GetSysVariableConf(ctx context.Context) entity.SysConfVariables {
if i18n.GetLocale(ctx) == i18n.LocaleEN {
return sysVariableConfEN
}
return sysVariableConf
}
func (v *variablesImpl) GetProjectVariablesMeta(ctx context.Context, projectID, version string) (*entity.VariablesMeta, error) {
return v.GetVariableMeta(ctx, projectID, project_memory.VariableConnector_Project, version)
}
func (v *variablesImpl) UpsertProjectMeta(ctx context.Context, projectID, version string, userID int64, e *entity.VariablesMeta) (int64, error) {
return v.upsertVariableMeta(ctx, projectID, project_memory.VariableConnector_Project, version, userID, e)
}
func (v *variablesImpl) UpsertMeta(ctx context.Context, e *entity.VariablesMeta) (int64, error) {
return v.upsertVariableMeta(ctx, e.BizID, e.BizType, e.Version, e.CreatorID, e)
}
func (v *variablesImpl) UpsertBotMeta(ctx context.Context, agentID int64, version string, userID int64, e *entity.VariablesMeta) (int64, error) {
bizID := fmt.Sprintf("%d", agentID)
return v.upsertVariableMeta(ctx, bizID, project_memory.VariableConnector_Bot, version, userID, e)
}
func (v *variablesImpl) upsertVariableMeta(ctx context.Context, bizID string, bizType project_memory.VariableConnector, version string, userID int64, e *entity.VariablesMeta) (int64, error) {
meta, err := v.Repo.GetVariableMeta(ctx, bizID, bizType, version)
if err != nil {
return 0, err
}
do := &entity.VariablesMeta{
BizID: bizID,
Version: version,
CreatorID: int64(userID),
BizType: bizType,
Variables: e.Variables,
}
if meta == nil {
return v.Repo.CreateVariableMeta(ctx, do, bizType)
}
do.ID = meta.ID
err = v.Repo.UpdateProjectVariable(ctx, do, bizType)
if err != nil {
return 0, err
}
return meta.ID, nil
}
func (*variablesImpl) mergeVariableList(_ context.Context, sysVarsList, variablesList []*entity.VariableMeta) *entity.VariablesMeta {
mergedMap := make(map[string]*entity.VariableMeta)
for _, sysVar := range sysVarsList {
mergedMap[sysVar.Keyword] = sysVar
}
// 可以覆盖 sysVar
for _, variable := range variablesList {
mergedMap[variable.Keyword] = variable
}
res := make([]*entity.VariableMeta, 0)
for _, variable := range mergedMap {
res = append(res, variable)
}
sort.Slice(res, func(i, j int) bool {
if res[i].Channel == project_memory.VariableChannel_System && !(res[j].Channel == project_memory.VariableChannel_System) {
return false
}
if !(res[i].Channel == project_memory.VariableChannel_System) && res[j].Channel == project_memory.VariableChannel_System {
return true
}
indexI := -1
indexJ := -1
for index, s := range sysVarsList {
if s.Keyword == res[i].Keyword {
indexI = index
}
if s.Keyword == res[j].Keyword {
indexJ = index
}
}
for index, s := range variablesList {
if s.Keyword == res[i].Keyword && indexI < 0 {
indexI = index
}
if s.Keyword == res[j].Keyword && indexJ < 0 {
indexJ = index
}
}
return indexI < indexJ
})
return &entity.VariablesMeta{
Variables: res,
}
}
func (v *variablesImpl) GetAgentVariableMeta(ctx context.Context, agentID int64, version string) (*entity.VariablesMeta, error) {
bizID := fmt.Sprintf("%d", agentID)
return v.GetVariableMeta(ctx, bizID, project_memory.VariableConnector_Bot, version)
}
func (v *variablesImpl) GetVariableMetaByID(ctx context.Context, id int64) (*entity.VariablesMeta, error) {
do, err := v.Repo.GetVariableMetaByID(ctx, id)
if err != nil {
return nil, err
}
if do == nil {
return nil, nil
}
return do, nil
}
func (v *variablesImpl) GetVariableMeta(ctx context.Context, bizID string, bizType project_memory.VariableConnector, version string) (*entity.VariablesMeta, error) {
data, err := v.Repo.GetVariableMeta(ctx, bizID, bizType, version)
if err != nil {
return nil, err
}
sysVarMeta := v.GetSysVariableConf(ctx)
if bizType == project_memory.VariableConnector_Project {
sysVarMeta.RemoveLocalChannelVariable()
}
sysVarMetaList := sysVarMeta.ToVariables()
if data == nil {
return sysVarMetaList, nil
}
resVarMetaList := v.mergeVariableList(ctx, sysVarMetaList.Variables, data.Variables)
resVarMetaList.SetupSchema()
resVarMetaList.SetupIsReadOnly()
return resVarMetaList, nil
}
func (v *variablesImpl) DeleteAllVariable(ctx context.Context, bizType project_memory.VariableConnector, bizID string) (err error) {
return v.Repo.DeleteAllVariableData(ctx, bizType, bizID)
}
func (v *variablesImpl) DeleteVariableInstance(ctx context.Context, e *entity.UserVariableMeta, keywords []string) (err error) {
// if e.BizType == int32(project_memory.VariableConnector_Project) {
// keywords = v.removeProjectSysVariable(ctx, keywords)
// } else {
// keywords, err = v.removeAgentSysVariable(ctx, keywords, e.BizID)
// if err != nil {
// return err
// }
// }
keywords = v.removeSysVariable(ctx, keywords)
if len(keywords) == 0 {
return errorx.New(errno.ErrMemoryNoVariableCanBeChangedCode)
}
return v.Repo.DeleteVariableInstance(ctx, e, keywords)
}
func (v *variablesImpl) removeAgentSysVariable(ctx context.Context, keywords []string, biz_id string) ([]string, error) {
vars, err := v.GetVariableMeta(ctx, biz_id, project_memory.VariableConnector_Bot, "")
if err != nil {
return nil, err
}
sysKeywords := make(map[string]bool)
for _, v := range vars.Variables {
if v.Channel == project_memory.VariableChannel_System {
sysKeywords[v.Keyword] = true
}
}
if len(sysKeywords) == 0 {
return keywords, nil
}
filteredKeywords := make([]string, 0)
for _, v := range keywords {
if sysKeywords[v] {
continue
}
filteredKeywords = append(filteredKeywords, v)
}
return filteredKeywords, nil
}
func (v *variablesImpl) removeSysVariable(ctx context.Context, keywords []string) []string {
sysConf := v.GetSysVariableConf(ctx)
sysVarsMap := make(map[string]bool)
for _, v := range sysConf {
sysVarsMap[v.Key] = true
}
filteredKeywords := make([]string, 0)
for _, v := range keywords {
if sysVarsMap[v] {
continue
}
filteredKeywords = append(filteredKeywords, v)
}
return filteredKeywords
}
func (v *variablesImpl) GetVariableInstance(ctx context.Context, e *entity.UserVariableMeta, keywords []string) ([]*kvmemory.KVItem, error) {
return v.GetVariableChannelInstance(ctx, e, keywords, nil)
}
func (v *variablesImpl) GetVariableChannelInstance(ctx context.Context, e *entity.UserVariableMeta, keywords []string, varChannel *project_memory.VariableChannel) ([]*kvmemory.KVItem, error) {
meta, err := v.GetVariableMeta(ctx, e.BizID, project_memory.VariableConnector(e.BizType), e.Version)
if err != nil {
return nil, err
}
if varChannel != nil {
meta.FilterChannelVariable(*varChannel)
}
meta.RemoveDisableVariable()
metaKey2Variable := map[string]*entity.VariableMeta{}
metaKeys := make([]string, 0, len(meta.Variables))
for _, variable := range meta.Variables {
metaKeys = append(metaKeys, variable.Keyword)
metaKey2Variable[variable.Keyword] = variable
}
kvInstances, err := v.Repo.GetVariableInstances(ctx, e, keywords)
if err != nil {
return nil, err
}
varBothInMetaAndInstance := map[string]*entity.VariableInstance{}
for _, v := range kvInstances {
if _, ok := metaKey2Variable[v.Keyword]; ok {
varBothInMetaAndInstance[v.Keyword] = v
}
}
newKeywords := ternary.IFElse(len(keywords) > 0, keywords, metaKeys)
resMemory := make([]*kvmemory.KVItem, 0, len(newKeywords))
for _, v := range newKeywords {
if vv, ok := varBothInMetaAndInstance[v]; ok {
meta := metaKey2Variable[v]
resMemory = append(resMemory, &kvmemory.KVItem{
Keyword: vv.Keyword,
Value: vv.Content,
CreateTime: vv.CreatedAt / 1000,
UpdateTime: vv.UpdatedAt / 1000,
Schema: meta.Schema,
IsSystem: meta.IsSystem(),
PromptDisabled: meta.PromptDisabled,
})
} else if vv, ok := metaKey2Variable[v]; ok { // only in meta
now := time.Now()
resMemory = append(resMemory, &kvmemory.KVItem{
Keyword: vv.Keyword,
Value: vv.DefaultValue,
CreateTime: now.Unix(),
UpdateTime: now.Unix(),
Schema: vv.Schema,
IsSystem: vv.IsSystem(),
PromptDisabled: vv.PromptDisabled,
})
}
}
sysKVItems, err := v.getSysKVItems(ctx, meta, e)
res := v.mergeKVItem(resMemory, sysKVItems)
res = v.sortKVItem(res, meta)
return res, nil
}
func (v *variablesImpl) getAppKVItems(_ context.Context, meta *entity.VariablesMeta) ([]*kvmemory.KVItem, error) {
resMemory := []*kvmemory.KVItem{}
for _, v := range meta.Variables {
if v.Channel == project_memory.VariableChannel_APP {
resMemory = append(resMemory, &kvmemory.KVItem{
Keyword: v.Keyword,
Value: v.DefaultValue,
Schema: v.Schema,
})
}
}
return resMemory, nil
}
func (v *variablesImpl) getSysKVItems(ctx context.Context, meta *entity.VariablesMeta, e *entity.UserVariableMeta) ([]*kvmemory.KVItem, error) {
sysKVItems := []*kvmemory.KVItem{}
for _, variable := range meta.Variables {
if variable.Channel == project_memory.VariableChannel_System {
sysKV, err := e.GenSystemKV(ctx, variable.Keyword)
if err != nil {
return nil, err
}
if sysKV != nil {
sysKVItems = append(sysKVItems, sysKV)
}
}
}
return sysKVItems, nil
}
func (v *variablesImpl) mergeKVItem(user []*kvmemory.KVItem, sys []*kvmemory.KVItem) []*kvmemory.KVItem {
res := make([]*kvmemory.KVItem, 0, len(user))
sysMap := make(map[string]bool)
for _, v := range sys {
res = append(res, v)
sysMap[v.Keyword] = true
}
for _, v := range user {
if sysMap[v.Keyword] {
continue
}
res = append(res, v)
}
return res
}
func (v *variablesImpl) sortKVItem(items []*kvmemory.KVItem, meta *entity.VariablesMeta) []*kvmemory.KVItem {
sort.Slice(items, func(ii, jj int) bool {
i := items[ii]
j := items[jj]
// 如果都是系统变量,这里不需要变换位置
if i.IsSystem && !j.IsSystem {
return false
}
if !i.IsSystem && j.IsSystem {
return true
}
indexI := -1
indexJ := -1
for index, s := range meta.Variables {
if s.Keyword == i.Keyword {
indexI = index
}
if s.Keyword == j.Keyword {
indexJ = index
}
}
return indexI < indexJ
})
return items
}
func (v *variablesImpl) SetVariableInstance(ctx context.Context, e *entity.UserVariableMeta, items []*kvmemory.KVItem) ([]string, error) {
meta, err := v.GetVariableMeta(ctx, e.BizID, project_memory.VariableConnector(e.BizType), e.Version)
if err != nil {
return nil, err
}
filerItems := v.filterKVItem(items, meta)
if len(filerItems) == 0 {
return nil, errorx.New(errno.ErrMemorySetKvMemoryItemInstanceCode)
}
keywords := make([]string, 0, len(filerItems))
key2Item := make(map[string]*kvmemory.KVItem, len(filerItems))
for _, v := range filerItems {
keywords = append(keywords, v.Keyword)
key2Item[v.Keyword] = v
}
kvInstances, err := v.Repo.GetVariableInstances(ctx, e, keywords)
if err != nil {
return nil, err
}
needUpdateKeywords := make([]string, 0, len(kvInstances))
needUpdateKVs := make([]*entity.VariableInstance, 0, len(kvInstances))
for _, v := range kvInstances {
if vv, ok := key2Item[v.Keyword]; ok {
needUpdateKeywords = append(needUpdateKeywords, v.Keyword)
v.Content = vv.Value
needUpdateKVs = append(needUpdateKVs, v)
delete(key2Item, v.Keyword)
}
}
err = v.Repo.UpdateVariableInstance(ctx, needUpdateKVs)
if err != nil {
return nil, err
}
needIndexKVs := make([]*entity.VariableInstance, 0, len(key2Item))
for _, v := range key2Item {
needIndexKVs = append(needIndexKVs, &entity.VariableInstance{
BizType: e.BizType,
BizID: e.BizID,
Version: e.Version,
ConnectorID: e.ConnectorID,
ConnectorUID: e.ConnectorUID,
Type: int32(project_memory.VariableType_KVVariable),
Keyword: v.Keyword,
Content: v.Value,
})
}
err = v.Repo.InsertVariableInstance(ctx, needIndexKVs)
if err != nil {
return nil, err
}
return needUpdateKeywords, nil
}
func (v *variablesImpl) filterKVItem(items []*kvmemory.KVItem, meta *entity.VariablesMeta) []*kvmemory.KVItem {
metaKey2Variable := map[string]*entity.VariableMeta{}
for _, variable := range meta.Variables {
metaKey2Variable[variable.Keyword] = variable
}
res := make([]*kvmemory.KVItem, 0, len(items))
for _, v := range items {
vv, ok := metaKey2Variable[v.Keyword]
if ok && vv.Channel != project_memory.VariableChannel_System {
res = append(res, v)
}
}
return res
}
func (v *variablesImpl) PublishMeta(ctx context.Context, variableMetaID int64, version string) (int64, error) {
e, err := v.Repo.GetVariableMetaByID(ctx, variableMetaID)
if err != nil {
return 0, err
}
if e == nil {
return 0, fmt.Errorf("%d,variable meta not found", variableMetaID)
}
e.Version = version
return v.Repo.CreateVariableMeta(ctx, e, project_memory.VariableConnector(e.BizType))
}
func (v *variablesImpl) DecryptSysUUIDKey(ctx context.Context, encryptSysUUIDKey string) *entity.VariableInstance {
meta := &entity.UserVariableMeta{}
return meta.DecryptSysUUIDKey(ctx, encryptSysUUIDKey)
}