Files
ai-agent/internal/ai/application/runtime/workflow_engine.go
T
mlogclub 34051a4631 feat: Enhance AI Agent and Channel Management
- 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.
2026-07-25 12:04:06 +08:00

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)