From acfce615ec918517e3d2648e6f6366374c26fb31 Mon Sep 17 00:00:00 2001 From: junwen-lee Date: Wed, 5 Nov 2025 21:35:17 +0800 Subject: [PATCH] feat: support conversation isolation (#2443) Co-authored-by: yangyu.1 --- .../conversation/conversation/conversation.go | 192 +++++++++++++++++- .../conversation/conversation_service.go | 18 +- backend/application/conversation/agent_run.go | 2 +- .../application/conversation/conversation.go | 12 +- backend/application/conversation/message.go | 2 +- .../conversation/openapi_agent_run.go | 7 +- .../conversation/openapi_agent_run_test.go | 3 +- backend/application/workflow/chatflow.go | 44 ++-- backend/application/workflow/workflow.go | 79 ++++--- .../conversation/model/conversation.go | 1 + .../conversation/entity/conversation.go | 6 +- .../conversation/internal/dal/dao.go | 9 +- .../internal/dal/model/conversation.gen.go | 3 +- .../internal/dal/query/conversation.gen.go | 14 +- .../conversation/service/conversation_impl.go | 3 +- .../conversation/service/conversation_test.go | 2 +- .../nodes/conversation/createconversation.go | 2 +- .../nodes/conversation/createmessage.go | 2 +- .../internal/nodes/database/common.go | 3 +- .../workflow/internal/nodes/plugin/exec.go | 2 +- .../workflow/service/conversation_impl.go | 6 +- .../migrations/20251028085526_update.sql | 2 + docker/atlas/migrations/atlas.sum | 3 +- docker/atlas/opencoze_latest_schema.hcl | 50 +++-- .../conversation-list/index.tsx | 4 + .../hooks/use-conversation-list.ts | 5 + .../coz-sdk/api-adapter/use-clear-history.ts | 8 +- .../provider/coz-sdk/use-request-init.ts | 11 +- idl/conversation/conversation.thrift | 5 + 29 files changed, 405 insertions(+), 95 deletions(-) create mode 100644 docker/atlas/migrations/20251028085526_update.sql diff --git a/backend/api/model/conversation/conversation/conversation.go b/backend/api/model/conversation/conversation/conversation.go index d44090f7e..c93f098ee 100644 --- a/backend/api/model/conversation/conversation/conversation.go +++ b/backend/api/model/conversation/conversation/conversation.go @@ -1,4 +1,20 @@ -// Code generated by thriftgo (0.4.2). DO NOT EDIT. +/* + * 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. + */ + +// Code generated by thriftgo (0.4.1). DO NOT EDIT. package conversation @@ -1033,6 +1049,7 @@ type ConversationData struct { LastSectionID *int64 `thrift:"LastSectionID,6,optional" form:"last_section_id" json:"last_section_id,string,omitempty"` AccountID *int64 `thrift:"AccountID,7,optional" form:"account_id" json:"account_id,omitempty"` Name *string `thrift:"Name,8,optional" form:"name" json:"name,omitempty"` + UserID *string `thrift:"UserID,9,optional" form:"user_id" json:"user_id,omitempty"` } func NewConversationData() *ConversationData { @@ -1099,6 +1116,15 @@ func (p *ConversationData) GetName() (v string) { return *p.Name } +var ConversationData_UserID_DEFAULT string + +func (p *ConversationData) GetUserID() (v string) { + if !p.IsSetUserID() { + return ConversationData_UserID_DEFAULT + } + return *p.UserID +} + var fieldIDToName_ConversationData = map[int16]string{ 1: "Id", 2: "CreatedAt", @@ -1108,6 +1134,7 @@ var fieldIDToName_ConversationData = map[int16]string{ 6: "LastSectionID", 7: "AccountID", 8: "Name", + 9: "UserID", } func (p *ConversationData) IsSetCreatorID() bool { @@ -1130,6 +1157,10 @@ func (p *ConversationData) IsSetName() bool { return p.Name != nil } +func (p *ConversationData) IsSetUserID() bool { + return p.UserID != nil +} + func (p *ConversationData) Read(iprot thrift.TProtocol) (err error) { var fieldTypeId thrift.TType var fieldId int16 @@ -1212,6 +1243,14 @@ func (p *ConversationData) Read(iprot thrift.TProtocol) (err error) { } else if err = iprot.Skip(fieldTypeId); err != nil { goto SkipFieldError } + case 9: + if fieldTypeId == thrift.STRING { + if err = p.ReadField9(iprot); err != nil { + goto ReadFieldError + } + } else if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } default: if err = iprot.Skip(fieldTypeId); err != nil { goto SkipFieldError @@ -1347,6 +1386,17 @@ func (p *ConversationData) ReadField8(iprot thrift.TProtocol) error { p.Name = _field return nil } +func (p *ConversationData) ReadField9(iprot thrift.TProtocol) error { + + var _field *string + if v, err := iprot.ReadString(); err != nil { + return err + } else { + _field = &v + } + p.UserID = _field + return nil +} func (p *ConversationData) Write(oprot thrift.TProtocol) (err error) { var fieldId int16 @@ -1386,6 +1436,10 @@ func (p *ConversationData) Write(oprot thrift.TProtocol) (err error) { fieldId = 8 goto WriteFieldError } + if err = p.writeField9(oprot); err != nil { + fieldId = 9 + goto WriteFieldError + } } if err = oprot.WriteFieldStop(); err != nil { goto WriteFieldStopError @@ -1553,6 +1607,24 @@ WriteFieldBeginError: WriteFieldEndError: return thrift.PrependError(fmt.Sprintf("%T write field 8 end error: ", p), err) } +func (p *ConversationData) writeField9(oprot thrift.TProtocol) (err error) { + if p.IsSetUserID() { + if err = oprot.WriteFieldBegin("UserID", thrift.STRING, 9); err != nil { + goto WriteFieldBeginError + } + if err := oprot.WriteString(*p.UserID); err != nil { + return err + } + if err = oprot.WriteFieldEnd(); err != nil { + goto WriteFieldEndError + } + } + return nil +WriteFieldBeginError: + return thrift.PrependError(fmt.Sprintf("%T write field 9 begin error: ", p), err) +WriteFieldEndError: + return thrift.PrependError(fmt.Sprintf("%T write field 9 end error: ", p), err) +} func (p *ConversationData) String() string { if p == nil { @@ -1567,6 +1639,7 @@ type CreateConversationRequest struct { MetaData map[string]string `thrift:"MetaData,1,optional" form:"meta_data" json:"meta_data,omitempty"` BotId *int64 `thrift:"BotId,3,optional" form:"bot_id" json:"bot_id,string,omitempty"` ConnectorId *int64 `thrift:"ConnectorId,4,optional" form:"connector_id" json:"connector_id,string,omitempty"` + UserID *string `thrift:"user_id,50,optional" form:"user_id" json:"user_id,omitempty"` } func NewCreateConversationRequest() *CreateConversationRequest { @@ -1603,10 +1676,20 @@ func (p *CreateConversationRequest) GetConnectorId() (v int64) { return *p.ConnectorId } +var CreateConversationRequest_UserID_DEFAULT string + +func (p *CreateConversationRequest) GetUserID() (v string) { + if !p.IsSetUserID() { + return CreateConversationRequest_UserID_DEFAULT + } + return *p.UserID +} + var fieldIDToName_CreateConversationRequest = map[int16]string{ - 1: "MetaData", - 3: "BotId", - 4: "ConnectorId", + 1: "MetaData", + 3: "BotId", + 4: "ConnectorId", + 50: "user_id", } func (p *CreateConversationRequest) IsSetMetaData() bool { @@ -1621,6 +1704,10 @@ func (p *CreateConversationRequest) IsSetConnectorId() bool { return p.ConnectorId != nil } +func (p *CreateConversationRequest) IsSetUserID() bool { + return p.UserID != nil +} + func (p *CreateConversationRequest) Read(iprot thrift.TProtocol) (err error) { var fieldTypeId thrift.TType var fieldId int16 @@ -1663,6 +1750,14 @@ func (p *CreateConversationRequest) Read(iprot thrift.TProtocol) (err error) { } else if err = iprot.Skip(fieldTypeId); err != nil { goto SkipFieldError } + case 50: + if fieldTypeId == thrift.STRING { + if err = p.ReadField50(iprot); err != nil { + goto ReadFieldError + } + } else if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } default: if err = iprot.Skip(fieldTypeId); err != nil { goto SkipFieldError @@ -1743,6 +1838,17 @@ func (p *CreateConversationRequest) ReadField4(iprot thrift.TProtocol) error { p.ConnectorId = _field return nil } +func (p *CreateConversationRequest) ReadField50(iprot thrift.TProtocol) error { + + var _field *string + if v, err := iprot.ReadString(); err != nil { + return err + } else { + _field = &v + } + p.UserID = _field + return nil +} func (p *CreateConversationRequest) Write(oprot thrift.TProtocol) (err error) { var fieldId int16 @@ -1762,6 +1868,10 @@ func (p *CreateConversationRequest) Write(oprot thrift.TProtocol) (err error) { fieldId = 4 goto WriteFieldError } + if err = p.writeField50(oprot); err != nil { + fieldId = 50 + goto WriteFieldError + } } if err = oprot.WriteFieldStop(); err != nil { goto WriteFieldStopError @@ -1845,6 +1955,24 @@ WriteFieldBeginError: WriteFieldEndError: return thrift.PrependError(fmt.Sprintf("%T write field 4 end error: ", p), err) } +func (p *CreateConversationRequest) writeField50(oprot thrift.TProtocol) (err error) { + if p.IsSetUserID() { + if err = oprot.WriteFieldBegin("user_id", thrift.STRING, 50); err != nil { + goto WriteFieldBeginError + } + if err := oprot.WriteString(*p.UserID); err != nil { + return err + } + if err = oprot.WriteFieldEnd(); err != nil { + goto WriteFieldEndError + } + } + return nil +WriteFieldBeginError: + return thrift.PrependError(fmt.Sprintf("%T write field 50 begin error: ", p), err) +WriteFieldEndError: + return thrift.PrependError(fmt.Sprintf("%T write field 50 end error: ", p), err) +} func (p *CreateConversationRequest) String() string { if p == nil { @@ -2771,6 +2899,7 @@ type ListConversationsApiRequest struct { SortField string `thrift:"sort_field,4" json:"sort_field" query:"sort_field"` BotID int64 `thrift:"bot_id,5,required" json:"bot_id,string,required" query:"bot_id,required"` ConnectorID *int64 `thrift:"connector_id,6,optional" json:"connector_id,string,omitempty" query:"connector_id"` + UserID *string `thrift:"user_id,50,optional" json:"user_id,omitempty" query:"user_id"` Base *base.Base `thrift:"Base,255" form:"Base" json:"Base" query:"Base"` } @@ -2810,6 +2939,15 @@ func (p *ListConversationsApiRequest) GetConnectorID() (v int64) { return *p.ConnectorID } +var ListConversationsApiRequest_UserID_DEFAULT string + +func (p *ListConversationsApiRequest) GetUserID() (v string) { + if !p.IsSetUserID() { + return ListConversationsApiRequest_UserID_DEFAULT + } + return *p.UserID +} + var ListConversationsApiRequest_Base_DEFAULT *base.Base func (p *ListConversationsApiRequest) GetBase() (v *base.Base) { @@ -2826,6 +2964,7 @@ var fieldIDToName_ListConversationsApiRequest = map[int16]string{ 4: "sort_field", 5: "bot_id", 6: "connector_id", + 50: "user_id", 255: "Base", } @@ -2833,6 +2972,10 @@ func (p *ListConversationsApiRequest) IsSetConnectorID() bool { return p.ConnectorID != nil } +func (p *ListConversationsApiRequest) IsSetUserID() bool { + return p.UserID != nil +} + func (p *ListConversationsApiRequest) IsSetBase() bool { return p.Base != nil } @@ -2905,6 +3048,14 @@ func (p *ListConversationsApiRequest) Read(iprot thrift.TProtocol) (err error) { } else if err = iprot.Skip(fieldTypeId); err != nil { goto SkipFieldError } + case 50: + if fieldTypeId == thrift.STRING { + if err = p.ReadField50(iprot); err != nil { + goto ReadFieldError + } + } else if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } case 255: if fieldTypeId == thrift.STRUCT { if err = p.ReadField255(iprot); err != nil { @@ -3014,6 +3165,17 @@ func (p *ListConversationsApiRequest) ReadField6(iprot thrift.TProtocol) error { p.ConnectorID = _field return nil } +func (p *ListConversationsApiRequest) ReadField50(iprot thrift.TProtocol) error { + + var _field *string + if v, err := iprot.ReadString(); err != nil { + return err + } else { + _field = &v + } + p.UserID = _field + return nil +} func (p *ListConversationsApiRequest) ReadField255(iprot thrift.TProtocol) error { _field := base.NewBase() if err := _field.Read(iprot); err != nil { @@ -3053,6 +3215,10 @@ func (p *ListConversationsApiRequest) Write(oprot thrift.TProtocol) (err error) fieldId = 6 goto WriteFieldError } + if err = p.writeField50(oprot); err != nil { + fieldId = 50 + goto WriteFieldError + } if err = p.writeField255(oprot); err != nil { fieldId = 255 goto WriteFieldError @@ -3173,6 +3339,24 @@ WriteFieldBeginError: WriteFieldEndError: return thrift.PrependError(fmt.Sprintf("%T write field 6 end error: ", p), err) } +func (p *ListConversationsApiRequest) writeField50(oprot thrift.TProtocol) (err error) { + if p.IsSetUserID() { + if err = oprot.WriteFieldBegin("user_id", thrift.STRING, 50); err != nil { + goto WriteFieldBeginError + } + if err := oprot.WriteString(*p.UserID); err != nil { + return err + } + if err = oprot.WriteFieldEnd(); err != nil { + goto WriteFieldEndError + } + } + return nil +WriteFieldBeginError: + return thrift.PrependError(fmt.Sprintf("%T write field 50 begin error: ", p), err) +WriteFieldEndError: + return thrift.PrependError(fmt.Sprintf("%T write field 50 end error: ", p), err) +} func (p *ListConversationsApiRequest) writeField255(oprot thrift.TProtocol) (err error) { if err = oprot.WriteFieldBegin("Base", thrift.STRUCT, 255); err != nil { goto WriteFieldBeginError diff --git a/backend/api/model/conversation/conversation/conversation_service.go b/backend/api/model/conversation/conversation/conversation_service.go index 97ed06f94..300a48b4c 100644 --- a/backend/api/model/conversation/conversation/conversation_service.go +++ b/backend/api/model/conversation/conversation/conversation_service.go @@ -1,4 +1,20 @@ -// Code generated by thriftgo (0.4.2). DO NOT EDIT. +/* + * 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. + */ + +// Code generated by thriftgo (0.4.1). DO NOT EDIT. package conversation diff --git a/backend/application/conversation/agent_run.go b/backend/application/conversation/agent_run.go index d9cd5810b..03d75bc41 100644 --- a/backend/application/conversation/agent_run.go +++ b/backend/application/conversation/agent_run.go @@ -269,7 +269,7 @@ func (c *ConversationApplicationService) checkConversation(ctx context.Context, conData, err := c.ConversationDomainSVC.Create(ctx, &convEntity.CreateMeta{ AgentID: ar.BotID, - UserID: userID, + CreatorID: userID, Scene: ptr.From(ar.Scene), ConnectorID: consts.CozeConnectorID, }) diff --git a/backend/application/conversation/conversation.go b/backend/application/conversation/conversation.go index 9e266bf55..9f8dfe954 100644 --- a/backend/application/conversation/conversation.go +++ b/backend/application/conversation/conversation.go @@ -83,7 +83,7 @@ func (c *ConversationApplicationService) ClearHistory(ctx context.Context, req * // create new conversation convRes, err := c.ConversationDomainSVC.Create(ctx, &entity.CreateMeta{ AgentID: currentRes.AgentID, - UserID: currentRes.CreatorID, + CreatorID: currentRes.CreatorID, Scene: currentRes.Scene, ConnectorID: consts.CozeConnectorID, }) @@ -126,7 +126,7 @@ func (c *ConversationApplicationService) CreateSection(ctx context.Context, conv func (c *ConversationApplicationService) CreateConversation(ctx context.Context, req *conversation.CreateConversationRequest) (*conversation.CreateConversationResponse, error) { resp := new(conversation.CreateConversationResponse) apiKeyInfo := ctxutil.GetApiAuthFromCtx(ctx) - userID := apiKeyInfo.UserID + creatorID := apiKeyInfo.UserID connectorID := req.GetConnectorId() agentID := req.GetBotId() if connectorID != consts.WebSDKConnectorID { @@ -135,7 +135,8 @@ func (c *ConversationApplicationService) CreateConversation(ctx context.Context, conversationData, err := c.ConversationDomainSVC.Create(ctx, &entity.CreateMeta{ AgentID: agentID, - UserID: userID, + UserID: req.UserID, + CreatorID: creatorID, ConnectorID: connectorID, Scene: common.Scene_SceneOpenApi, Ext: parseMetaData(req.MetaData), @@ -149,6 +150,7 @@ func (c *ConversationApplicationService) CreateConversation(ctx context.Context, ConnectorID: &conversationData.ConnectorID, CreatedAt: conversationData.CreatedAt / 1000, MetaData: parseExt(conversationData.Ext), + UserID: conversationData.UserID, } return resp, nil } @@ -191,7 +193,7 @@ func (c *ConversationApplicationService) ListConversation(ctx context.Context, r } conversationDOList, hasMore, err := c.ConversationDomainSVC.List(ctx, &entity.ListMeta{ - UserID: userID, + CreatorID: userID, AgentID: req.GetBotID(), ConnectorID: connectorID, Scene: common.Scene_SceneOpenApi, @@ -203,6 +205,7 @@ func (c *ConversationApplicationService) ListConversation(ctx context.Context, r } return nil }(), + UserID: req.UserID, }) if err != nil { return resp, err @@ -215,6 +218,7 @@ func (c *ConversationApplicationService) ListConversation(ctx context.Context, r CreatedAt: conv.CreatedAt / 1000, Name: ptr.Of(conv.Name), MetaData: parseExt(conv.Ext), + UserID: conv.UserID, } }) diff --git a/backend/application/conversation/message.go b/backend/application/conversation/message.go index 697a98963..627a8bc56 100644 --- a/backend/application/conversation/message.go +++ b/backend/application/conversation/message.go @@ -141,7 +141,7 @@ func (c *ConversationApplicationService) getCurrentConversation(ctx context.Cont // create conversation ccNew, err := c.ConversationDomainSVC.Create(ctx, &convEntity.CreateMeta{ AgentID: agentID, - UserID: userID, + CreatorID: userID, Scene: scene, ConnectorID: ptr.From(connectorID), }) diff --git a/backend/application/conversation/openapi_agent_run.go b/backend/application/conversation/openapi_agent_run.go index 92c85445f..7c1444c16 100644 --- a/backend/application/conversation/openapi_agent_run.go +++ b/backend/application/conversation/openapi_agent_run.go @@ -91,7 +91,7 @@ func (a *OpenapiAgentRunApplication) OpenapiAgentRun(ctx context.Context, sseSen return nil } -func (a *OpenapiAgentRunApplication) checkConversation(ctx context.Context, ar *run.ChatV3Request, userID int64, connectorID int64) (*convEntity.Conversation, error) { +func (a *OpenapiAgentRunApplication) checkConversation(ctx context.Context, ar *run.ChatV3Request, creatorID int64, connectorID int64) (*convEntity.Conversation, error) { var conversationData *convEntity.Conversation if ptr.From(ar.ConversationID) > 0 { conData, err := ConversationSVC.ConversationDomainSVC.GetByID(ctx, ptr.From(ar.ConversationID)) @@ -105,9 +105,10 @@ func (a *OpenapiAgentRunApplication) checkConversation(ctx context.Context, ar * conData, err := ConversationSVC.ConversationDomainSVC.Create(ctx, &convEntity.CreateMeta{ AgentID: ar.BotID, - UserID: userID, + CreatorID: creatorID, ConnectorID: connectorID, Scene: common.Scene_SceneOpenApi, + UserID: ptr.Of(ar.User), }) if err != nil { return nil, err @@ -120,7 +121,7 @@ func (a *OpenapiAgentRunApplication) checkConversation(ctx context.Context, ar * ar.ConversationID = ptr.Of(conversationData.ID) } - if conversationData.CreatorID != userID { + if conversationData.CreatorID != creatorID { return nil, errorx.New(errno.ErrConversationPermissionCode, errorx.KV("msg", "user not match")) } diff --git a/backend/application/conversation/openapi_agent_run_test.go b/backend/application/conversation/openapi_agent_run_test.go index bbabc6211..a2358a758 100644 --- a/backend/application/conversation/openapi_agent_run_test.go +++ b/backend/application/conversation/openapi_agent_run_test.go @@ -283,10 +283,11 @@ func TestOpenapiAgentRun_CreateNewConversation(t *testing.T) { ID: 22222, CreatorID: 12345, SectionID: 98765, + UserID: ptr.Of("test-user"), } mockConversation.EXPECT().Create(ctx, gomock.Any()).DoAndReturn(func(ctx context.Context, meta *convEntity.CreateMeta) (*convEntity.Conversation, error) { assert.Equal(t, int64(67890), meta.AgentID) - assert.Equal(t, int64(12345), meta.UserID) + assert.Equal(t, "test-user", ptr.From(meta.UserID)) assert.Equal(t, common.Scene_SceneOpenApi, meta.Scene) return mockConv, nil }) diff --git a/backend/application/workflow/chatflow.go b/backend/application/workflow/chatflow.go index 5b90c210c..ce308b164 100644 --- a/backend/application/workflow/chatflow.go +++ b/backend/application/workflow/chatflow.go @@ -550,6 +550,12 @@ func (w *ApplicationService) OpenAPIChatFlowRun(ctx context.Context, req *workfl apiKeyInfo = ctxutil.GetApiAuthFromCtx(ctx) userID = apiKeyInfo.UserID connectorID int64 + runtimeUserID = func() *string { + if uID, ok := req.Ext["user_id"]; ok { + return ptr.Of(uID) + } + return nil + }() ) if len(req.GetConnectorID()) == 0 { connectorID = ternary.IFElse(isDebug, consts.CozeConnectorID, apiKeyInfo.ConnectorID) @@ -676,11 +682,16 @@ func (w *ApplicationService) OpenAPIChatFlowRun(ctx context.Context, req *workfl ExecuteID: info.ExecID, ResumeData: lastUserMessage.Content, }, workflowModel.ExecuteConfig{ - Operator: userID, - Mode: ternary.IFElse(isDebug, workflowModel.ExecuteModeDebug, workflowModel.ExecuteModeRelease), - ConnectorID: connectorID, - ConnectorUID: strconv.FormatInt(userID, 10), - BizType: workflowModel.BizTypeWorkflow, + Operator: userID, + Mode: ternary.IFElse(isDebug, workflowModel.ExecuteModeDebug, workflowModel.ExecuteModeRelease), + ConnectorID: connectorID, + ConnectorUID: func() string { + if runtimeUserID != nil { + return *runtimeUserID + } + return strconv.FormatInt(userID, 10) + }(), + BizType: workflowModel.BizTypeWorkflow, }) if err != nil { @@ -704,15 +715,20 @@ func (w *ApplicationService) OpenAPIChatFlowRun(ctx context.Context, req *workfl } exeCfg := workflowModel.ExecuteConfig{ - ID: mustParseInt64(req.GetWorkflowID()), - From: locator, - Version: version, - Operator: userID, - Mode: ternary.IFElse(isDebug, workflowModel.ExecuteModeDebug, workflowModel.ExecuteModeRelease), - AppID: appID, - AgentID: agentID, - ConnectorID: connectorID, - ConnectorUID: strconv.FormatInt(userID, 10), + ID: mustParseInt64(req.GetWorkflowID()), + From: locator, + Version: version, + Operator: userID, + Mode: ternary.IFElse(isDebug, workflowModel.ExecuteModeDebug, workflowModel.ExecuteModeRelease), + AppID: appID, + AgentID: agentID, + ConnectorID: connectorID, + ConnectorUID: func() string { + if runtimeUserID != nil { + return *runtimeUserID + } + return strconv.FormatInt(userID, 10) + }(), TaskType: workflowModel.TaskTypeForeground, SyncPattern: workflowModel.SyncPatternStream, InputFailFast: true, diff --git a/backend/application/workflow/workflow.go b/backend/application/workflow/workflow.go index ad79a6ac0..18d20ac61 100644 --- a/backend/application/workflow/workflow.go +++ b/backend/application/workflow/workflow.go @@ -1513,6 +1513,12 @@ func (w *ApplicationService) OpenAPIStreamRun(ctx context.Context, req *workflow apiKeyInfo := ctxutil.GetApiAuthFromCtx(ctx) userID := apiKeyInfo.UserID + runtimeUserID := func() *string { + if uID, ok := req.Ext["user_id"]; ok { + return ptr.Of(uID) + } + return nil + }() parameters := make(map[string]any) if req.Parameters != nil { err := sonic.UnmarshalString(*req.Parameters, ¶meters) @@ -1557,15 +1563,20 @@ func (w *ApplicationService) OpenAPIStreamRun(ctx context.Context, req *workflow } exeCfg := workflowModel.ExecuteConfig{ - ID: meta.ID, - From: workflowModel.FromSpecificVersion, - Version: *meta.LatestPublishedVersion, - Operator: userID, - Mode: workflowModel.ExecuteModeRelease, - AppID: appID, - AgentID: agentID, - ConnectorID: connectorID, - ConnectorUID: strconv.FormatInt(userID, 10), + ID: meta.ID, + From: workflowModel.FromSpecificVersion, + Version: *meta.LatestPublishedVersion, + Operator: userID, + Mode: workflowModel.ExecuteModeRelease, + AppID: appID, + AgentID: agentID, + ConnectorID: connectorID, + ConnectorUID: func() string { + if runtimeUserID != nil { + return *runtimeUserID + } + return strconv.FormatInt(userID, 10) + }(), TaskType: workflowModel.TaskTypeForeground, SyncPattern: workflowModel.SyncPatternStream, InputFailFast: true, @@ -1624,6 +1635,12 @@ func (w *ApplicationService) OpenAPIStreamResume(ctx context.Context, req *workf apiKeyInfo := ctxutil.GetApiAuthFromCtx(ctx) userID := apiKeyInfo.UserID + runtimeUserID := func() *string { + if uID, ok := req.Ext["user_id"]; ok { + return ptr.Of(uID) + } + return nil + }() checkResult, err := crosspermission.DefaultSVC().CheckAuthz(ctx, &permission.CheckAuthzData{ OperatorID: userID, @@ -1650,11 +1667,16 @@ func (w *ApplicationService) OpenAPIStreamResume(ctx context.Context, req *workf } sr, err := GetWorkflowDomainSVC().StreamResume(ctx, resumeReq, workflowModel.ExecuteConfig{ - Operator: userID, - Mode: workflowModel.ExecuteModeRelease, - ConnectorID: connectorID, - ConnectorUID: strconv.FormatInt(userID, 10), - BizType: workflowModel.BizTypeWorkflow, + Operator: userID, + Mode: workflowModel.ExecuteModeRelease, + ConnectorID: connectorID, + ConnectorUID: func() string { + if runtimeUserID != nil { + return *runtimeUserID + } + return strconv.FormatInt(userID, 10) + }(), + BizType: workflowModel.BizTypeWorkflow, }) if err != nil { return nil, err @@ -1680,6 +1702,12 @@ func (w *ApplicationService) OpenAPIRun(ctx context.Context, req *workflow.OpenA apiKeyInfo := ctxutil.GetApiAuthFromCtx(ctx) userID := apiKeyInfo.UserID + runtimeUserID := func() *string { + if uID, ok := req.Ext["user_id"]; ok { + return ptr.Of(uID) + } + return nil + }() parameters := make(map[string]any) if req.Parameters != nil { @@ -1725,15 +1753,20 @@ func (w *ApplicationService) OpenAPIRun(ctx context.Context, req *workflow.OpenA } exeCfg := workflowModel.ExecuteConfig{ - ID: meta.ID, - From: workflowModel.FromSpecificVersion, - Version: *meta.LatestPublishedVersion, - Operator: userID, - Mode: workflowModel.ExecuteModeRelease, - AppID: appID, - AgentID: agentID, - ConnectorID: connectorID, - ConnectorUID: strconv.FormatInt(userID, 10), + ID: meta.ID, + From: workflowModel.FromSpecificVersion, + Version: *meta.LatestPublishedVersion, + Operator: userID, + Mode: workflowModel.ExecuteModeRelease, + AppID: appID, + AgentID: agentID, + ConnectorID: connectorID, + ConnectorUID: func() string { + if runtimeUserID != nil { + return *runtimeUserID + } + return strconv.FormatInt(userID, 10) + }(), InputFailFast: true, BizType: workflowModel.BizTypeWorkflow, } diff --git a/backend/crossdomain/conversation/model/conversation.go b/backend/crossdomain/conversation/model/conversation.go index b515c1aad..b6e6c0289 100644 --- a/backend/crossdomain/conversation/model/conversation.go +++ b/backend/crossdomain/conversation/model/conversation.go @@ -47,6 +47,7 @@ type Conversation struct { AgentID int64 `json:"agent_id"` ConnectorID int64 `json:"connector_id"` CreatorID int64 `json:"creator_id"` + UserID *string `json:"user_id"` Scene common.Scene `json:"scene"` Status ConversationStatus `json:"status"` Ext string `json:"ext"` diff --git a/backend/domain/conversation/conversation/entity/conversation.go b/backend/domain/conversation/conversation/entity/conversation.go index e7f1cd3d8..bbd15e523 100644 --- a/backend/domain/conversation/conversation/entity/conversation.go +++ b/backend/domain/conversation/conversation/entity/conversation.go @@ -26,7 +26,8 @@ type Conversation = model.Conversation type CreateMeta struct { Name string `json:"name"` AgentID int64 `json:"agent_id"` - UserID int64 `json:"user_id"` + UserID *string `json:"user_id"` + CreatorID int64 `json:"creator_id"` ConnectorID int64 `json:"connector_id"` Scene common.Scene `json:"scene"` Ext string `json:"ext"` @@ -44,7 +45,8 @@ type NewConversationCtxResponse struct { type GetCurrent = model.GetCurrent type ListMeta struct { - UserID int64 `json:"user_id"` + CreatorID int64 `json:"creator_id"` + UserID *string `json:"user_id"` ConnectorID int64 `json:"connector_id"` Scene common.Scene `json:"scene"` AgentID int64 `json:"agent_id"` diff --git a/backend/domain/conversation/conversation/internal/dal/dao.go b/backend/domain/conversation/conversation/internal/dal/dao.go index 400dafed8..4019e3936 100644 --- a/backend/domain/conversation/conversation/internal/dal/dao.go +++ b/backend/domain/conversation/conversation/internal/dal/dao.go @@ -145,12 +145,16 @@ func (dao *ConversationDAO) List(ctx context.Context, listMeta *entity.ListMeta) var hasMore bool do := dao.query.Conversation.WithContext(ctx).Debug() - do = do.Where(dao.query.Conversation.CreatorID.Eq(listMeta.UserID)). + do = do.Where(dao.query.Conversation.CreatorID.Eq(listMeta.CreatorID)). Where(dao.query.Conversation.AgentID.Eq(listMeta.AgentID)). Where(dao.query.Conversation.Scene.Eq(int32(listMeta.Scene))). Where(dao.query.Conversation.ConnectorID.Eq(listMeta.ConnectorID)). Where(dao.query.Conversation.Status.Eq(int32(conversation.ConversationStatusNormal))) + if listMeta.UserID != nil { + do = do.Where(dao.query.Conversation.UserID.Eq(ptr.From(listMeta.UserID))) + } + do = do.Offset((listMeta.Page - 1) * listMeta.Limit) if listMeta.Limit > 0 { @@ -188,6 +192,7 @@ func (dao *ConversationDAO) conversationDO2PO(ctx context.Context, conversation SectionID: conversation.SectionID, ConnectorID: conversation.ConnectorID, AgentID: conversation.AgentID, + UserID: ptr.From(conversation.UserID), CreatorID: conversation.CreatorID, Scene: int32(conversation.Scene), Status: int32(conversation.Status), @@ -211,6 +216,7 @@ func (dao *ConversationDAO) conversationPO2DO(ctx context.Context, c *model.Conv CreatedAt: c.CreatedAt, UpdatedAt: c.UpdatedAt, Name: c.Name, + UserID: ptr.Of(c.UserID), } } @@ -228,6 +234,7 @@ func (dao *ConversationDAO) conversationBatchPO2DO(ctx context.Context, conversa CreatedAt: c.CreatedAt, UpdatedAt: c.UpdatedAt, Name: c.Name, + UserID: ptr.Of(c.UserID), } }) } diff --git a/backend/domain/conversation/conversation/internal/dal/model/conversation.gen.go b/backend/domain/conversation/conversation/internal/dal/model/conversation.gen.go index 6838dd202..210e1d8c7 100644 --- a/backend/domain/conversation/conversation/internal/dal/model/conversation.gen.go +++ b/backend/domain/conversation/conversation/internal/dal/model/conversation.gen.go @@ -25,7 +25,6 @@ const TableNameConversation = "conversation" // Conversation conversation info record type Conversation struct { ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:id" json:"id"` // id - Name string `gorm:"column:name;not null;comment:conversation name" json:"name"` // conversation name ConnectorID int64 `gorm:"column:connector_id;not null;comment:Publish Connector ID" json:"connector_id"` // Publish Connector ID AgentID int64 `gorm:"column:agent_id;not null;comment:agent_id" json:"agent_id"` // agent_id Scene int32 `gorm:"column:scene;not null;comment:conversation scene" json:"scene"` // conversation scene @@ -35,6 +34,8 @@ type Conversation struct { Status int32 `gorm:"column:status;not null;default:1;comment:status: 1-normal 2-deleted" json:"status"` // status: 1-normal 2-deleted CreatedAt int64 `gorm:"column:created_at;not null;autoCreateTime:milli;comment:Create Time in Milliseconds" json:"created_at"` // Create Time in Milliseconds UpdatedAt int64 `gorm:"column:updated_at;not null;autoUpdateTime:milli;comment:Update Time in Milliseconds" json:"updated_at"` // Update Time in Milliseconds + Name string `gorm:"column:name;not null;comment:conversation name" json:"name"` // conversation name + UserID string `gorm:"column:user_id;not null;comment:user id" json:"user_id"` // user id } // TableName Conversation's table name diff --git a/backend/domain/conversation/conversation/internal/dal/query/conversation.gen.go b/backend/domain/conversation/conversation/internal/dal/query/conversation.gen.go index a2755e0e1..b680b4f85 100644 --- a/backend/domain/conversation/conversation/internal/dal/query/conversation.gen.go +++ b/backend/domain/conversation/conversation/internal/dal/query/conversation.gen.go @@ -44,7 +44,6 @@ func newConversation(db *gorm.DB, opts ...gen.DOOption) conversation { tableName := _conversation.conversationDo.TableName() _conversation.ALL = field.NewAsterisk(tableName) _conversation.ID = field.NewInt64(tableName, "id") - _conversation.Name = field.NewString(tableName, "name") _conversation.ConnectorID = field.NewInt64(tableName, "connector_id") _conversation.AgentID = field.NewInt64(tableName, "agent_id") _conversation.Scene = field.NewInt32(tableName, "scene") @@ -54,6 +53,8 @@ func newConversation(db *gorm.DB, opts ...gen.DOOption) conversation { _conversation.Status = field.NewInt32(tableName, "status") _conversation.CreatedAt = field.NewInt64(tableName, "created_at") _conversation.UpdatedAt = field.NewInt64(tableName, "updated_at") + _conversation.Name = field.NewString(tableName, "name") + _conversation.UserID = field.NewString(tableName, "user_id") _conversation.fillFieldMap() @@ -66,7 +67,6 @@ type conversation struct { ALL field.Asterisk ID field.Int64 // id - Name field.String // conversation name ConnectorID field.Int64 // Publish Connector ID AgentID field.Int64 // agent_id Scene field.Int32 // conversation scene @@ -76,6 +76,8 @@ type conversation struct { Status field.Int32 // status: 1-normal 2-deleted CreatedAt field.Int64 // Create Time in Milliseconds UpdatedAt field.Int64 // Update Time in Milliseconds + Name field.String // conversation name + UserID field.String // user id fieldMap map[string]field.Expr } @@ -93,7 +95,6 @@ func (c conversation) As(alias string) *conversation { func (c *conversation) updateTableName(table string) *conversation { c.ALL = field.NewAsterisk(table) c.ID = field.NewInt64(table, "id") - c.Name = field.NewString(table, "name") c.ConnectorID = field.NewInt64(table, "connector_id") c.AgentID = field.NewInt64(table, "agent_id") c.Scene = field.NewInt32(table, "scene") @@ -103,6 +104,8 @@ func (c *conversation) updateTableName(table string) *conversation { c.Status = field.NewInt32(table, "status") c.CreatedAt = field.NewInt64(table, "created_at") c.UpdatedAt = field.NewInt64(table, "updated_at") + c.Name = field.NewString(table, "name") + c.UserID = field.NewString(table, "user_id") c.fillFieldMap() @@ -119,9 +122,8 @@ func (c *conversation) GetFieldByName(fieldName string) (field.OrderExpr, bool) } func (c *conversation) fillFieldMap() { - c.fieldMap = make(map[string]field.Expr, 11) + c.fieldMap = make(map[string]field.Expr, 12) c.fieldMap["id"] = c.ID - c.fieldMap["name"] = c.Name c.fieldMap["connector_id"] = c.ConnectorID c.fieldMap["agent_id"] = c.AgentID c.fieldMap["scene"] = c.Scene @@ -131,6 +133,8 @@ func (c *conversation) fillFieldMap() { c.fieldMap["status"] = c.Status c.fieldMap["created_at"] = c.CreatedAt c.fieldMap["updated_at"] = c.UpdatedAt + c.fieldMap["name"] = c.Name + c.fieldMap["user_id"] = c.UserID } func (c conversation) clone(db *gorm.DB) conversation { diff --git a/backend/domain/conversation/conversation/service/conversation_impl.go b/backend/domain/conversation/conversation/service/conversation_impl.go index 1b6f94491..38792276b 100644 --- a/backend/domain/conversation/conversation/service/conversation_impl.go +++ b/backend/domain/conversation/conversation/service/conversation_impl.go @@ -40,11 +40,12 @@ func (c *conversationImpl) Create(ctx context.Context, req *entity.CreateMeta) ( var resp *entity.Conversation doData := &entity.Conversation{ - CreatorID: req.UserID, + CreatorID: req.CreatorID, AgentID: req.AgentID, Scene: req.Scene, ConnectorID: req.ConnectorID, Ext: req.Ext, + UserID: req.UserID, } resp, err := c.ConversationRepo.Create(ctx, doData) diff --git a/backend/domain/conversation/conversation/service/conversation_test.go b/backend/domain/conversation/conversation/service/conversation_test.go index 4a184ad2d..8598eae4c 100644 --- a/backend/domain/conversation/conversation/service/conversation_test.go +++ b/backend/domain/conversation/conversation/service/conversation_test.go @@ -57,7 +57,7 @@ func TestCreateConversation(t *testing.T) { createData, err := NewService(components).Create(ctx, &entity.CreateMeta{ AgentID: 100000, - UserID: 222222, + CreatorID: 222222, ConnectorID: 100001, Scene: common.Scene_Playground, Ext: "debug ext9999", diff --git a/backend/domain/workflow/internal/nodes/conversation/createconversation.go b/backend/domain/workflow/internal/nodes/conversation/createconversation.go index 63122e1a1..d0e5df4b8 100644 --- a/backend/domain/workflow/internal/nodes/conversation/createconversation.go +++ b/backend/domain/workflow/internal/nodes/conversation/createconversation.go @@ -79,7 +79,7 @@ func (c *CreateConversation) Invoke(ctx context.Context, input map[string]any) ( conversationIDGenerator = workflow.ConversationIDGenerator(func(ctx context.Context, appID int64, userID, connectorID int64) (*conventity.Conversation, error) { return crossconversation.DefaultSVC().CreateConversation(ctx, &conventity.CreateMeta{ AgentID: appID, - UserID: userID, + CreatorID: userID, ConnectorID: connectorID, Scene: common.Scene_SceneWorkflow, }) diff --git a/backend/domain/workflow/internal/nodes/conversation/createmessage.go b/backend/domain/workflow/internal/nodes/conversation/createmessage.go index 8879d826a..810ef121c 100644 --- a/backend/domain/workflow/internal/nodes/conversation/createmessage.go +++ b/backend/domain/workflow/internal/nodes/conversation/createmessage.go @@ -89,7 +89,7 @@ func (c *CreateMessage) getConversationIDByName(ctx context.Context, env vo.Env, conversationIDGenerator := workflow.ConversationIDGenerator(func(ctx context.Context, appID int64, userID, connectorID int64) (*conventity.Conversation, error) { return crossconversation.DefaultSVC().CreateConversation(ctx, &conventity.CreateMeta{ AgentID: appID, - UserID: userID, + CreatorID: userID, ConnectorID: connectorID, Scene: common.Scene_SceneWorkflow, }) diff --git a/backend/domain/workflow/internal/nodes/database/common.go b/backend/domain/workflow/internal/nodes/database/common.go index 607b183cd..fd346942e 100644 --- a/backend/domain/workflow/internal/nodes/database/common.go +++ b/backend/domain/workflow/internal/nodes/database/common.go @@ -421,9 +421,10 @@ func getExecUserID(ctx context.Context) string { if execCtx == nil { panic(fmt.Errorf("unable to get exe context")) } - if execCtx.RootCtx.ExeCfg.AgentID != nil { + if execCtx.RootCtx.ExeCfg.ConnectorUID != "" { return execCtx.RootCtx.ExeCfg.ConnectorUID } + uIDStr := strconv.FormatInt(execCtx.RootCtx.ExeCfg.Operator, 10) return uIDStr } diff --git a/backend/domain/workflow/internal/nodes/plugin/exec.go b/backend/domain/workflow/internal/nodes/plugin/exec.go index 23e4e41b7..bcb890d09 100644 --- a/backend/domain/workflow/internal/nodes/plugin/exec.go +++ b/backend/domain/workflow/internal/nodes/plugin/exec.go @@ -43,7 +43,7 @@ func ExecutePlugin(ctx context.Context, input map[string]any, pe *vo.PluginEntit } var uID string - if cfg.AgentID != nil { + if cfg.ConnectorUID != "" { uID = cfg.ConnectorUID } else { uID = conv.Int64ToStr(cfg.Operator) diff --git a/backend/domain/workflow/service/conversation_impl.go b/backend/domain/workflow/service/conversation_impl.go index dc2ef5db2..24859e987 100644 --- a/backend/domain/workflow/service/conversation_impl.go +++ b/backend/domain/workflow/service/conversation_impl.go @@ -363,7 +363,7 @@ func (c *conversationImpl) GetOrCreateConversation(ctx context.Context, env vo.E conversationIDGenerator := workflow.ConversationIDGenerator(func(ctx context.Context, bizID int64, userID, connectorID int64) (*conventity.Conversation, error) { return crossconversation.DefaultSVC().CreateConversation(ctx, &conventity.CreateMeta{ AgentID: bizID, - UserID: userID, + CreatorID: userID, ConnectorID: connectorID, Scene: common.Scene_SceneWorkflow, }) @@ -408,7 +408,7 @@ func (c *conversationImpl) UpdateConversation(ctx context.Context, env vo.Env, a if existed { conv, err := crossconversation.DefaultSVC().CreateConversation(ctx, &conventity.CreateMeta{ AgentID: appID, - UserID: userID, + CreatorID: userID, ConnectorID: connectorID, Scene: common.Scene_SceneWorkflow, }) @@ -436,7 +436,7 @@ func (c *conversationImpl) UpdateConversation(ctx context.Context, env vo.Env, a conv, err := crossconversation.DefaultSVC().CreateConversation(ctx, &conventity.CreateMeta{ AgentID: appID, - UserID: userID, + CreatorID: userID, ConnectorID: connectorID, Scene: common.Scene_SceneWorkflow, }) diff --git a/docker/atlas/migrations/20251028085526_update.sql b/docker/atlas/migrations/20251028085526_update.sql new file mode 100644 index 000000000..d6a955b49 --- /dev/null +++ b/docker/atlas/migrations/20251028085526_update.sql @@ -0,0 +1,2 @@ +-- Modify "conversation" table +ALTER TABLE `opencoze`.`conversation` ADD COLUMN `user_id` varchar(255) NOT NULL DEFAULT "" COMMENT "user id with runtime"; diff --git a/docker/atlas/migrations/atlas.sum b/docker/atlas/migrations/atlas.sum index 5cc644330..95d7b1219 100644 --- a/docker/atlas/migrations/atlas.sum +++ b/docker/atlas/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:fRmZ1DqaVJmbdXGbkWkJGCWbHy3gTQxkg6KRhpDBYeA= +h1:rpu8MnfqHOGZgvvh8p2w3lMlIMNBL/6X1UZ6ng6v4oM= 20250703095335_initial.sql h1:/joaeUTMhXqAEc0KwsSve5+bYM0qPOp+9OizJtsRc+U= 20250703115304_update.sql h1:cbYo6Q6Lh96hB4hu5KW2Nn/Mr0VDpg7a1WPgpIb1SOc= 20250704040445_update.sql h1:QWmoPY//oQ+GFZwET9w/oAWa8mM0KVaD5G8Yiu9bMqY= @@ -15,3 +15,4 @@ h1:fRmZ1DqaVJmbdXGbkWkJGCWbHy3gTQxkg6KRhpDBYeA= 20251015103940_update.sql h1:ivE+qtF4q3bMFroid1yMSO465s5Oiey/5VvQ7GWnBlY= 20251016034721_update.sql h1:BLXpKpa3LBVyiuMDGSwud6WwM+34jQQvn11ytYZCbrw= 20251024091145_update.sql h1:WH/24vD2bYK6udS7GRO1Enzw81SjCpRcbOSkzUhiMrk= +20251028085526_update.sql h1:Nv8QPX8ctvnQmDeA8z4kr1ltTEULErgD7FxpMHyzYCg= diff --git a/docker/atlas/opencoze_latest_schema.hcl b/docker/atlas/opencoze_latest_schema.hcl index 5961fa70d..2b19a632c 100644 --- a/docker/atlas/opencoze_latest_schema.hcl +++ b/docker/atlas/opencoze_latest_schema.hcl @@ -1016,12 +1016,6 @@ table "conversation" { comment = "id" auto_increment = true } - column "name" { - null = true - type = varchar(255) - default = "" - comment = "conversation name" - } column "connector_id" { null = false type = bigint @@ -1080,6 +1074,18 @@ table "conversation" { unsigned = true comment = "Update Time in Milliseconds" } + column "name" { + null = true + type = varchar(255) + default = "" + comment = "conversation name" + } + column "user_id" { + null = false + type = varchar(255) + default = "" + comment = "user id with runtime" + } primary_key { columns = [column.id] } @@ -3256,6 +3262,11 @@ table "single_agent_draft" { type = json comment = "Agent Database Base Configuration" } + column "shortcut_command" { + null = true + type = json + comment = "shortcut command" + } column "bot_mode" { null = false type = tinyint @@ -3267,11 +3278,6 @@ table "single_agent_draft" { type = text comment = "chatflow layout info" } - column "shortcut_command" { - null = true - type = json - comment = "shortcut command" - } primary_key { columns = [column.id] } @@ -3428,17 +3434,6 @@ table "single_agent_version" { unsigned = true comment = "Create Time in Milliseconds" } - column "bot_mode" { - null = false - type = tinyint - default = 0 - comment = "bot mode,0:single mode 2:chatflow mode" - } - column "layout_info" { - null = true - type = text - comment = "chatflow layout info" - } column "updated_at" { null = false type = bigint @@ -3523,6 +3518,17 @@ table "single_agent_version" { type = json comment = "shortcut command" } + column "bot_mode" { + null = false + type = tinyint + default = 0 + comment = "bot mode,0:single mode 2:chatflow mode" + } + column "layout_info" { + null = true + type = text + comment = "chatflow layout info" + } primary_key { columns = [column.id] } diff --git a/frontend/packages/studio/open-platform/open-chat/src/components/conversation-list-sider/conversation-list/index.tsx b/frontend/packages/studio/open-platform/open-chat/src/components/conversation-list-sider/conversation-list/index.tsx index dd67e06d3..e213790e4 100644 --- a/frontend/packages/studio/open-platform/open-chat/src/components/conversation-list-sider/conversation-list/index.tsx +++ b/frontend/packages/studio/open-platform/open-chat/src/components/conversation-list-sider/conversation-list/index.tsx @@ -34,6 +34,7 @@ import { type SortedConversationItem, } from '@/types/conversations'; import { Layout } from '@/types/client'; +import { useUserInfo } from '@/components/studio-open-chat/hooks'; import { PcConversationItem, @@ -93,6 +94,8 @@ export const ConversationList = forwardRef< })), ); + const userInfo = useUserInfo(); + const conversationRef = useRef(); const [addLoading, setAddLoading] = useState(false); const { @@ -114,6 +117,7 @@ export const ConversationList = forwardRef< bot_id: botId, // @ts-expect-error: 有这个属性,但是 openapi 没有暴露 connector_id: connectorId, + user_id: IS_OPEN_SOURCE ? userInfo?.id : undefined, }); if (res?.id) { conversationRef.current = { diff --git a/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/hooks/use-conversation-list.ts b/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/hooks/use-conversation-list.ts index c2dfdc496..c172a1601 100644 --- a/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/hooks/use-conversation-list.ts +++ b/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/hooks/use-conversation-list.ts @@ -27,11 +27,13 @@ import { import { type ChatState } from '../store/store'; import { useChatAppProps, useChatAppStore } from '../store'; +import { useUserInfo } from './use-user-info'; import { usePaginationRequest } from './use-pagination-request'; // 扩展ListConversationReq类型以满足PaginationParams约束 type ExtendedListConversationReq = ListConversationReq & { sort_field: 'created_at' | 'updated_at'; + user_id?: string; // 开源专有 [key: string]: unknown; }; @@ -76,6 +78,8 @@ export const useConversationList = ( })), ); + const userInfo = useUserInfo(); + const { data, hasMore, loadMore, loading } = usePaginationRequest< Conversation, ExtendedListConversationReq @@ -99,6 +103,7 @@ export const useConversationList = ( bot_id: botId, connector_id: connectorId, sort_field: order, + user_id: IS_OPEN_SOURCE ? userInfo?.id : undefined, }, pageSize, initialPageNum, diff --git a/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/provider/coz-sdk/api-adapter/use-clear-history.ts b/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/provider/coz-sdk/api-adapter/use-clear-history.ts index 32a884d39..01930ff79 100644 --- a/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/provider/coz-sdk/api-adapter/use-clear-history.ts +++ b/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/provider/coz-sdk/api-adapter/use-clear-history.ts @@ -20,6 +20,7 @@ import { type SceneConfig } from '@coze-common/chat-core'; import { OpenApiSource } from '@/types/open'; import { useChatAppProps } from '@/components/studio-open-chat/store'; +import { useUserInfo } from '@/components/studio-open-chat/hooks'; import { type ChatProviderFunc } from '../type'; export const useClearHistoryAdapter = ({ @@ -29,6 +30,7 @@ export const useClearHistoryAdapter = ({ }): SceneConfig => { const { chatConfig } = useChatAppProps(); const refConnectorId = useRef(''); + const userInfo = useUserInfo(); refConnectorId.current = chatConfig?.auth?.connectorId || ''; return useMemo(() => { @@ -60,7 +62,11 @@ export const useClearHistoryAdapter = ({ const botId = requestConfig.data.bot_id; return { ...requestConfig, - data: { bot_id: botId, connector_id: refConnectorId.current }, + data: { + bot_id: botId, + connector_id: refConnectorId.current, + user_id: IS_OPEN_SOURCE ? userInfo?.id : undefined, + }, }; }, ], diff --git a/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/provider/coz-sdk/use-request-init.ts b/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/provider/coz-sdk/use-request-init.ts index 6de9ff0a1..75d4431c6 100644 --- a/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/provider/coz-sdk/use-request-init.ts +++ b/frontend/packages/studio/open-platform/open-chat/src/components/studio-open-chat/provider/coz-sdk/use-request-init.ts @@ -17,7 +17,10 @@ import { useCallback } from 'react'; import { type ShortCutCommand } from '@coze-common/chat-area-plugins-chat-shortcuts'; -import { type MixInitResponse } from '@coze-common/chat-area'; +import { + type UserSenderInfo, + type MixInitResponse, +} from '@coze-common/chat-area'; import i18n from '@coze-arch/i18n/intl'; import { type BotInfo, type CozeAPI } from '@coze/api'; @@ -134,12 +137,14 @@ const getConversationInfo = async ({ connectorId, defaultHistoryMessage, onDefaultHistoryClear, + userInfo, }: GetRequestInfoProps & { conversationId?: string; sectionId?: string; connectorId: string; defaultHistoryMessage?: MixInitResponse['messageList']; onDefaultHistoryClear?: () => void; + userInfo: UserSenderInfo | null; }): Promise< Pick< MixInitResponse, @@ -161,6 +166,7 @@ const getConversationInfo = async ({ connector_id: connectorId, page_num: 1, page_size: 1, + user_id: IS_OPEN_SOURCE ? userInfo?.id : undefined, }, )) as { data: { @@ -185,6 +191,7 @@ const getConversationInfo = async ({ messages: historyMessage, // @ts-expect-error: connector_id is not in the type connector_id: connectorId, + user_id: IS_OPEN_SOURCE ? userInfo?.id : undefined, }, { headers: { @@ -204,6 +211,7 @@ const getConversationInfo = async ({ bot_id: botId, // @ts-expect-error: connector_id is not in the type connector_id: connectorId, + user_id: IS_OPEN_SOURCE ? userInfo?.id : undefined, }, { headers: { @@ -329,6 +337,7 @@ export const useRequestInit = () => { connectorId, onDefaultHistoryClear, defaultHistoryMessage, + userInfo, }), ]); const prologue = (requestDataBotInfo.prologue || '').replaceAll( diff --git a/idl/conversation/conversation.thrift b/idl/conversation/conversation.thrift index 5dc022fb3..0f9468c48 100644 --- a/idl/conversation/conversation.thrift +++ b/idl/conversation/conversation.thrift @@ -37,12 +37,15 @@ struct ConversationData { 6: optional i64 LastSectionID (api.body="last_section_id", api.js_conv="true") 7: optional i64 AccountID (api.body = "account_id") 8: optional string Name (api.body = "name") + 9: optional string UserID (api.body = "user_id") } struct CreateConversationRequest { 1: optional map MetaData (api.body = "meta_data") //custom passthrough field 3: optional i64 BotId (api.body = "bot_id", api.js_conv="true") 4: optional i64 ConnectorId (api.body= "connector_id", api.js_conv="true") + + 50: optional string user_id (api.body="user_id") } struct CreateConversationResponse { @@ -78,6 +81,8 @@ struct ListConversationsApiRequest { 5 : required i64 bot_id (api.query = "bot_id", agw.key = "bot_id",api.js_conv="true") 6 : optional i64 connector_id (api.query = "connector_id", agw.key = "connector_id",api.js_conv="true") + 50 : optional string user_id (api.query = "user_id", agw.key = "user_id") + 255: base.Base Base }