34051a4631
- Updated labels in the AI Agents dashboard for clarity, changing "流程状态" to "Playbook 状态" and "未发布流程" to "未发布 Playbook". - Introduced AI Agent rollout percentage management in channel editing, allowing users to set and rollback rollout percentages. - Added new API endpoints for rolling back AI Agent rollout and fetching agent run metrics. - Implemented new UI components for displaying agent run details, including status, duration, and input/output tokens. - Enhanced type definitions for AdminChannel and AIAgent to include rollout percentages and runtime modes. - Updated navigation to include a section for agent runs. - Added new translations for agent run features in both English and Chinese.
113 lines
3.7 KiB
Go
113 lines
3.7 KiB
Go
package runtime
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
workflowexecutor "agent-desk/internal/ai/runtime/workflow"
|
|
"agent-desk/internal/pkg/errorsx"
|
|
"agent-desk/internal/pkg/utils"
|
|
"agent-desk/internal/repositories"
|
|
|
|
"github.com/mlogclub/simple/sqls"
|
|
)
|
|
|
|
// WorkflowEngine preserves the existing FlowGram DSL execution path as the
|
|
// first Agent Runtime engine. It remains the compatibility default for agents
|
|
// created before autonomous and hybrid modes are available.
|
|
type WorkflowEngine struct{}
|
|
|
|
func NewWorkflowEngine() *WorkflowEngine {
|
|
return &WorkflowEngine{}
|
|
}
|
|
|
|
func (e *WorkflowEngine) Code() string {
|
|
return EngineCodeWorkflow
|
|
}
|
|
|
|
func (e *WorkflowEngine) Run(ctx context.Context, req RunInput) (*RunResult, error) {
|
|
req.UserMessage.Content = utils.BuildRuntimeMessageText(req.UserMessage.MessageType, req.UserMessage.Content)
|
|
aiAgent, workflow, err := prepareWorkflowAgent(req.AIAgent)
|
|
if err != nil {
|
|
_, _ = writeWorkflowPrepareFailedRun(req, err.Error())
|
|
return nil, err
|
|
}
|
|
req.AIAgent = aiAgent
|
|
workflowResult, err := workflowexecutor.NewExecutor().Execute(ctx, workflowexecutor.Input{
|
|
Definition: workflow.Definition,
|
|
Conversation: req.Conversation,
|
|
UserMessage: req.UserMessage,
|
|
AIAgent: req.AIAgent,
|
|
AIConfig: req.AIConfig,
|
|
Debug: req.Debug,
|
|
})
|
|
if err != nil {
|
|
if workflowResult != nil {
|
|
_, _, _ = writeWorkflowRun(req, workflow, workflowResult, err.Error())
|
|
}
|
|
return nil, err
|
|
}
|
|
workflowRunID, agentRunID, err := writeWorkflowRun(req, workflow, workflowResult, "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return toWorkflowSummary(workflowResult, req.AIConfig.ModelName, workflow, workflowRunID, agentRunID), nil
|
|
}
|
|
|
|
func (e *WorkflowEngine) Resume(ctx context.Context, req ResumeInput) (*RunResult, error) {
|
|
aiAgent, workflow, err := prepareWorkflowAgent(req.AIAgent)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.AIAgent = aiAgent
|
|
interrupt := repositories.ConversationInterruptRepository.GetByCheckPointID(sqls.DB(), req.CheckPointID)
|
|
if interrupt == nil {
|
|
return nil, errorsx.InvalidParam("legacy checkpoint is not supported; please start a new workflow reply")
|
|
}
|
|
if strings.TrimSpace(interrupt.RequestData) == "" {
|
|
if interrupt.WorkflowRunID > 0 || strings.HasPrefix(strings.TrimSpace(req.CheckPointID), "workflow:") {
|
|
return nil, errorsx.InvalidParam("workflow checkpoint data is required")
|
|
}
|
|
return nil, errorsx.InvalidParam("legacy checkpoint is not supported; please start a new workflow reply")
|
|
}
|
|
workflowResult, err := workflowexecutor.NewExecutor().Resume(ctx, workflowexecutor.Input{
|
|
Definition: workflow.Definition,
|
|
Conversation: req.Conversation,
|
|
AIAgent: req.AIAgent,
|
|
AIConfig: req.AIConfig,
|
|
Debug: req.Debug,
|
|
}, interrupt.RequestData, firstWorkflowResumeText(req.ResumeData))
|
|
if err != nil {
|
|
if workflowResult != nil {
|
|
_, _, _ = writeWorkflowRunWithExistingID(Request{
|
|
Conversation: req.Conversation,
|
|
UserMessage: req.UserMessage,
|
|
AIAgent: req.AIAgent,
|
|
AIConfig: req.AIConfig,
|
|
}, workflow, workflowResult, err.Error(), interrupt.WorkflowRunID)
|
|
}
|
|
return nil, err
|
|
}
|
|
workflowRunID, agentRunID, err := writeWorkflowRunWithExistingID(Request{
|
|
Conversation: req.Conversation,
|
|
UserMessage: req.UserMessage,
|
|
AIAgent: req.AIAgent,
|
|
AIConfig: req.AIConfig,
|
|
}, workflow, workflowResult, "", interrupt.WorkflowRunID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return toWorkflowSummary(workflowResult, req.AIConfig.ModelName, workflow, workflowRunID, agentRunID), nil
|
|
}
|
|
|
|
func firstWorkflowResumeText(data map[string]string) string {
|
|
for _, value := range data {
|
|
if strings.TrimSpace(value) != "" {
|
|
return strings.TrimSpace(value)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
var _ Engine = (*WorkflowEngine)(nil)
|