215 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Go
		
	
	
	
| /*
 | |
|  * 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 internal
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/cloudwego/eino/schema"
 | |
| 
 | |
| 	"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
 | |
| 	"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/agentrun"
 | |
| 	"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/singleagent"
 | |
| 	crossmessage "github.com/coze-dev/coze-studio/backend/crossdomain/contract/message"
 | |
| 	"github.com/coze-dev/coze-studio/backend/domain/conversation/agentrun/entity"
 | |
| 	"github.com/coze-dev/coze-studio/backend/domain/conversation/agentrun/repository"
 | |
| 	msgEntity "github.com/coze-dev/coze-studio/backend/domain/conversation/message/entity"
 | |
| 	"github.com/coze-dev/coze-studio/backend/infra/contract/imagex"
 | |
| 	"github.com/coze-dev/coze-studio/backend/pkg/logs"
 | |
| 	"github.com/coze-dev/coze-studio/backend/types/errno"
 | |
| )
 | |
| 
 | |
| type AgentRuntime struct {
 | |
| 	RunRecord     *entity.RunRecordMeta
 | |
| 	AgentInfo     *singleagent.SingleAgent
 | |
| 	QuestionMsgID int64
 | |
| 	RunMeta       *entity.AgentRunMeta
 | |
| 	StartTime     time.Time
 | |
| 	Input         *msgEntity.Message
 | |
| 	HistoryMsg    []*msgEntity.Message
 | |
| 	Usage         *agentrun.Usage
 | |
| 	SW            *schema.StreamWriter[*entity.AgentRunResponse]
 | |
| 
 | |
| 	RunProcess    *RunProcess
 | |
| 	RunRecordRepo repository.RunRecordRepo
 | |
| 	ImagexClient  imagex.ImageX
 | |
| 	MessageEvent  *Event
 | |
| }
 | |
| 
 | |
| func (rd *AgentRuntime) SetRunRecord(runRecord *entity.RunRecordMeta) {
 | |
| 	rd.RunRecord = runRecord
 | |
| }
 | |
| 
 | |
| func (rd *AgentRuntime) GetRunRecord() *entity.RunRecordMeta {
 | |
| 	return rd.RunRecord
 | |
| }
 | |
| 
 | |
| func (rd *AgentRuntime) SetUsage(usage *agentrun.Usage) {
 | |
| 	rd.Usage = usage
 | |
| }
 | |
| func (rd *AgentRuntime) GetUsage() *agentrun.Usage {
 | |
| 	return rd.Usage
 | |
| }
 | |
| 
 | |
| func (rd *AgentRuntime) SetRunMeta(arm *entity.AgentRunMeta) {
 | |
| 	rd.RunMeta = arm
 | |
| }
 | |
| func (rd *AgentRuntime) GetRunMeta() *entity.AgentRunMeta {
 | |
| 	return rd.RunMeta
 | |
| }
 | |
| func (rd *AgentRuntime) SetAgentInfo(agentInfo *singleagent.SingleAgent) {
 | |
| 	rd.AgentInfo = agentInfo
 | |
| }
 | |
| func (rd *AgentRuntime) GetAgentInfo() *singleagent.SingleAgent {
 | |
| 	return rd.AgentInfo
 | |
| }
 | |
| func (rd *AgentRuntime) SetQuestionMsgID(msgID int64) {
 | |
| 	rd.QuestionMsgID = msgID
 | |
| }
 | |
| func (rd *AgentRuntime) GetQuestionMsgID() int64 {
 | |
| 	return rd.QuestionMsgID
 | |
| }
 | |
| func (rd *AgentRuntime) SetStartTime(t time.Time) {
 | |
| 	rd.StartTime = t
 | |
| }
 | |
| func (rd *AgentRuntime) GetStartTime() time.Time {
 | |
| 	return rd.StartTime
 | |
| }
 | |
| func (rd *AgentRuntime) SetInput(input *msgEntity.Message) {
 | |
| 	rd.Input = input
 | |
| }
 | |
| func (rd *AgentRuntime) GetInput() *msgEntity.Message {
 | |
| 	return rd.Input
 | |
| }
 | |
| 
 | |
| func (rd *AgentRuntime) SetHistoryMsg(histroyMsg []*msgEntity.Message) {
 | |
| 	rd.HistoryMsg = histroyMsg
 | |
| }
 | |
| 
 | |
| func (rd *AgentRuntime) GetHistory() []*msgEntity.Message {
 | |
| 	return rd.HistoryMsg
 | |
| }
 | |
| 
 | |
| func (art *AgentRuntime) Run(ctx context.Context) (err error) {
 | |
| 
 | |
| 	agentInfo, err := getAgentInfo(ctx, art.GetRunMeta().AgentID, art.GetRunMeta().IsDraft)
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	art.SetAgentInfo(agentInfo)
 | |
| 
 | |
| 	history, err := art.getHistory(ctx)
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	runRecord, err := art.createRunRecord(ctx)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	art.SetRunRecord(runRecord)
 | |
| 	art.SetHistoryMsg(history)
 | |
| 
 | |
| 	defer func() {
 | |
| 		srRecord := buildSendRunRecord(ctx, runRecord, entity.RunStatusCompleted)
 | |
| 		if err != nil {
 | |
| 			srRecord.Error = &entity.RunError{
 | |
| 				Code: errno.ErrConversationAgentRunError,
 | |
| 				Msg:  err.Error(),
 | |
| 			}
 | |
| 			art.RunProcess.StepToFailed(ctx, srRecord, art.SW)
 | |
| 			return
 | |
| 		}
 | |
| 		art.RunProcess.StepToComplete(ctx, srRecord, art.SW, art.GetUsage())
 | |
| 	}()
 | |
| 	mh := &MesssageEventHanlder{
 | |
| 		messageEvent: art.MessageEvent,
 | |
| 		sw:           art.SW,
 | |
| 	}
 | |
| 	input, err := mh.HandlerInput(ctx, art)
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 	art.SetInput(input)
 | |
| 
 | |
| 	art.SetQuestionMsgID(input.ID)
 | |
| 
 | |
| 	if art.GetAgentInfo().BotMode == bot_common.BotMode_WorkflowMode {
 | |
| 		err = art.ChatflowRun(ctx, art.ImagexClient)
 | |
| 	} else {
 | |
| 		err = art.AgentStreamExecute(ctx, art.ImagexClient)
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (art *AgentRuntime) getHistory(ctx context.Context) ([]*msgEntity.Message, error) {
 | |
| 
 | |
| 	conversationTurns := getAgentHistoryRounds(art.GetAgentInfo())
 | |
| 
 | |
| 	runRecordList, err := art.RunRecordRepo.List(ctx, &entity.ListRunRecordMeta{
 | |
| 		ConversationID: art.GetRunMeta().ConversationID,
 | |
| 		SectionID:      art.GetRunMeta().SectionID,
 | |
| 		Limit:          conversationTurns,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	if len(runRecordList) == 0 {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 	runIDS := concactRunID(runRecordList)
 | |
| 	history, err := crossmessage.DefaultSVC().GetByRunIDs(ctx, art.GetRunMeta().ConversationID, runIDS)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return history, nil
 | |
| }
 | |
| 
 | |
| func concactRunID(rr []*entity.RunRecordMeta) []int64 {
 | |
| 	ids := make([]int64, 0, len(rr))
 | |
| 	for _, c := range rr {
 | |
| 		ids = append(ids, c.ID)
 | |
| 	}
 | |
| 
 | |
| 	return ids
 | |
| }
 | |
| 
 | |
| func (art *AgentRuntime) createRunRecord(ctx context.Context) (*entity.RunRecordMeta, error) {
 | |
| 	runPoData, err := art.RunRecordRepo.Create(ctx, art.GetRunMeta())
 | |
| 	if err != nil {
 | |
| 		logs.CtxErrorf(ctx, "RunRecordRepo.Create error: %v", err)
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	srRecord := buildSendRunRecord(ctx, runPoData, entity.RunStatusCreated)
 | |
| 
 | |
| 	art.RunProcess.StepToCreate(ctx, srRecord, art.SW)
 | |
| 
 | |
| 	err = art.RunProcess.StepToInProgress(ctx, srRecord, art.SW)
 | |
| 	if err != nil {
 | |
| 		logs.CtxErrorf(ctx, "runProcess.StepToInProgress error: %v", err)
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return runPoData, nil
 | |
| }
 |