diff --git a/internal/ai/application/runtime/service.go b/internal/ai/application/runtime/service.go index 343a9fa..6e3f3e7 100644 --- a/internal/ai/application/runtime/service.go +++ b/internal/ai/application/runtime/service.go @@ -24,7 +24,11 @@ func NewService() *Service { func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) { req.UserMessage.Content = utils.BuildRuntimeMessageText(req.UserMessage.MessageType, req.UserMessage.Content) - req.AIAgent = applyWorkflowInstruction(req.AIAgent) + aiAgent, err := prepareWorkflowAgent(req.AIAgent) + if err != nil { + return nil, err + } + req.AIAgent = aiAgent toolSet, err := s.prepare.prepareToolsForRun(req) if err != nil { return nil, err @@ -45,7 +49,11 @@ func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) { } func (s *Service) Resume(ctx context.Context, req ResumeRequest) (*Summary, error) { - req.AIAgent = applyWorkflowInstruction(req.AIAgent) + aiAgent, err := prepareWorkflowAgent(req.AIAgent) + if err != nil { + return nil, err + } + req.AIAgent = aiAgent toolSet, err := s.prepare.prepareToolsForResume(req) if err != nil { return nil, err diff --git a/internal/ai/application/runtime/tool_catalog.go b/internal/ai/application/runtime/tool_catalog.go index ac31a81..1f27d95 100644 --- a/internal/ai/application/runtime/tool_catalog.go +++ b/internal/ai/application/runtime/tool_catalog.go @@ -82,7 +82,7 @@ func (c *toolCatalog) parseAgentAllowedToolCodes(aiAgent models.AIAgent) []strin ret = append(ret, graphTools...) } } - if result, ok := resolveAgentWorkflow(aiAgent); ok { + if result, err := resolveAgentWorkflow(aiAgent); err == nil { ret = append(ret, result.ToolCodes...) } return toolx.NormalizeToolCodes(ret) diff --git a/internal/ai/application/runtime/tool_catalog_test.go b/internal/ai/application/runtime/tool_catalog_test.go index 8b0c29e..94717fe 100644 --- a/internal/ai/application/runtime/tool_catalog_test.go +++ b/internal/ai/application/runtime/tool_catalog_test.go @@ -85,7 +85,6 @@ func TestToolCatalogIncludesPublishedWorkflowGraphTools(t *testing.T) { catalog := newToolCatalog() ret := catalog.parseAgentAllowedToolCodes(models.AIAgent{ - RuntimeMode: enums.AIAgentRuntimeModeWorkflow, WorkflowVersionID: version.ID, }) @@ -94,7 +93,7 @@ func TestToolCatalogIncludesPublishedWorkflowGraphTools(t *testing.T) { assertContainsToolCode(t, ret, toolx.GraphHandoffConversation.Code) } -func TestApplyWorkflowInstructionAppendsPublishedWorkflow(t *testing.T) { +func TestPrepareWorkflowAgentAppendsPublishedWorkflow(t *testing.T) { setupWorkflowRuntimeTestDB(t) version := createWorkflowRuntimeTestVersion(t, dsl.Definition{ SchemaVersion: 1, @@ -105,11 +104,13 @@ func TestApplyWorkflowInstructionAppendsPublishedWorkflow(t *testing.T) { }, }) - agent := applyWorkflowInstruction(models.AIAgent{ + agent, err := prepareWorkflowAgent(models.AIAgent{ SystemPrompt: "Base prompt.", - RuntimeMode: enums.AIAgentRuntimeModeWorkflow, WorkflowVersionID: version.ID, }) + if err != nil { + t.Fatalf("prepare workflow agent: %v", err) + } if agent.SystemPrompt == "Base prompt." { t.Fatalf("expected workflow appendix to be appended") } @@ -118,6 +119,39 @@ func TestApplyWorkflowInstructionAppendsPublishedWorkflow(t *testing.T) { } } +func TestPrepareWorkflowAgentRejectsMissingPublishedWorkflow(t *testing.T) { + _, err := prepareWorkflowAgent(models.AIAgent{}) + if err == nil { + t.Fatalf("expected missing workflow version error") + } + if !strings.Contains(err.Error(), "workflow version is required") { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestPrepareWorkflowAgentRejectsDeletedPublishedWorkflow(t *testing.T) { + setupWorkflowRuntimeTestDB(t) + version := createWorkflowRuntimeTestVersion(t, dsl.Definition{ + SchemaVersion: 1, + EntryNodeID: "start", + Nodes: []dsl.Node{ + {ID: "start", Type: workflowregistry.NodeTypeStart, Name: "Start"}, + {ID: "end", Type: workflowregistry.NodeTypeEnd, Name: "End"}, + }, + }) + if err := sqls.DB().Model(&models.AIWorkflowVersion{}).Where("id = ?", version.ID).Update("status", enums.StatusDeleted).Error; err != nil { + t.Fatalf("delete workflow version: %v", err) + } + + _, err := prepareWorkflowAgent(models.AIAgent{WorkflowVersionID: version.ID}) + if err == nil { + t.Fatalf("expected invalid workflow version error") + } + if !strings.Contains(err.Error(), "workflow version does not exist") { + t.Fatalf("unexpected error: %v", err) + } +} + func setupWorkflowRuntimeTestDB(t *testing.T) { t.Helper() db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=shared"), &gorm.Config{}) diff --git a/internal/ai/application/runtime/workflow_runtime.go b/internal/ai/application/runtime/workflow_runtime.go index 2042972..3b702ee 100644 --- a/internal/ai/application/runtime/workflow_runtime.go +++ b/internal/ai/application/runtime/workflow_runtime.go @@ -8,37 +8,41 @@ import ( "agent-desk/internal/ai/workflow/dsl" "agent-desk/internal/models" "agent-desk/internal/pkg/enums" + "agent-desk/internal/pkg/errorsx" "agent-desk/internal/repositories" "github.com/mlogclub/simple/sqls" ) -func resolveAgentWorkflow(aiAgent models.AIAgent) (compiler.Result, bool) { - if aiAgent.RuntimeMode != enums.AIAgentRuntimeModeWorkflow || aiAgent.WorkflowVersionID <= 0 { - return compiler.Result{}, false +func resolveAgentWorkflow(aiAgent models.AIAgent) (compiler.Result, error) { + if aiAgent.WorkflowVersionID <= 0 { + return compiler.Result{}, errorsx.InvalidParam("workflow version is required") } version := repositories.AIWorkflowVersionRepository.Get(sqls.DB(), aiAgent.WorkflowVersionID) if version == nil || version.Status != enums.StatusOk { - return compiler.Result{}, false + return compiler.Result{}, errorsx.InvalidParam("workflow version does not exist") } var def dsl.Definition if err := json.Unmarshal([]byte(version.Definition), &def); err != nil { - return compiler.Result{}, false + return compiler.Result{}, errorsx.InvalidParam("workflow definition is invalid") } - return compiler.Compile(def), true + return compiler.Compile(def), nil } -func applyWorkflowInstruction(aiAgent models.AIAgent) models.AIAgent { - result, ok := resolveAgentWorkflow(aiAgent) - if !ok || strings.TrimSpace(result.Appendix) == "" { - return aiAgent +func prepareWorkflowAgent(aiAgent models.AIAgent) (models.AIAgent, error) { + result, err := resolveAgentWorkflow(aiAgent) + if err != nil { + return aiAgent, err + } + if strings.TrimSpace(result.Appendix) == "" { + return aiAgent, nil } prompt := strings.TrimSpace(aiAgent.SystemPrompt) appendix := strings.TrimSpace(result.Appendix) if prompt == "" { aiAgent.SystemPrompt = appendix - return aiAgent + return aiAgent, nil } aiAgent.SystemPrompt = prompt + "\n\n" + appendix - return aiAgent + return aiAgent, nil } diff --git a/internal/handlers/dashboard/ai_agent_handler.go b/internal/handlers/dashboard/ai_agent_handler.go index cb39e1f..768cd93 100644 --- a/internal/handlers/dashboard/ai_agent_handler.go +++ b/internal/handlers/dashboard/ai_agent_handler.go @@ -189,8 +189,6 @@ func buildAIAgentResponseWithLocale(item *models.AIAgent, locale string) respons Teams: make([]response.AIAgentTeamResponse, 0), DirectTools: make([]response.AIAgentMCPToolResponse, 0), GraphTools: make([]string, 0), - RuntimeMode: item.RuntimeMode, - RuntimeModeName: enums.GetAIAgentRuntimeModeLabel(item.RuntimeMode), WorkflowVersionID: item.WorkflowVersionID, SortNo: item.SortNo, CreatedAt: item.CreatedAt.Format("2006-01-02 15:04:05"), diff --git a/internal/models/models.go b/internal/models/models.go index c467d64..d19d326 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -527,7 +527,6 @@ type AIAgent struct { SkillIDs string `gorm:"type:varchar(500);not null;default:''"` // SkillIDs 为绑定的技能ID列表,按顺序表示允许路由的范围。 AllowedMCPTools string `gorm:"type:text"` // AllowedMCPTools 为允许 direct tool 路由的 MCP 工具白名单配置JSON。 AllowedGraphTools string `gorm:"type:text"` // AllowedGraphTools 为允许 Graph Tool 的白名单配置JSON。 - RuntimeMode enums.AIAgentRuntimeMode `gorm:"type:int;not null;default:1;index"` // RuntimeMode 为 Agent 执行模式,如内置 Graph 或发布的会话流程。 WorkflowVersionID int64 `gorm:"type:bigint;not null;default:0;index"` // WorkflowVersionID 为绑定的已发布会话流程版本ID。 SortNo int `gorm:"type:int;not null;default:0;index"` // SortNo 为后台展示排序号。 AuditFields diff --git a/internal/pkg/dto/response/ai_response.go b/internal/pkg/dto/response/ai_response.go index b1764cc..cc7ca62 100644 --- a/internal/pkg/dto/response/ai_response.go +++ b/internal/pkg/dto/response/ai_response.go @@ -91,8 +91,6 @@ type AIAgentResponse struct { Skills []AIAgentSkillResponse `json:"skills"` DirectTools []AIAgentMCPToolResponse `json:"directTools"` GraphTools []string `json:"graphTools"` - RuntimeMode enums.AIAgentRuntimeMode `json:"runtimeMode"` - RuntimeModeName string `json:"runtimeModeName"` WorkflowVersionID int64 `json:"workflowVersionId"` SortNo int `json:"sortNo"` CreatedAt string `json:"createdAt"` diff --git a/internal/pkg/enums/ai.go b/internal/pkg/enums/ai.go index c17d7d5..3f9ffd3 100644 --- a/internal/pkg/enums/ai.go +++ b/internal/pkg/enums/ai.go @@ -31,24 +31,3 @@ var aiModelTypeLabelMap = map[AIModelType]string{ func GetAIModelTypeLabel(modelType AIModelType) string { return aiModelTypeLabelMap[modelType] } - -type AIAgentRuntimeMode int - -const ( - AIAgentRuntimeModeBuiltinGraph AIAgentRuntimeMode = 1 - AIAgentRuntimeModeWorkflow AIAgentRuntimeMode = 2 -) - -var AIAgentRuntimeModeValues = []AIAgentRuntimeMode{ - AIAgentRuntimeModeBuiltinGraph, - AIAgentRuntimeModeWorkflow, -} - -var aiAgentRuntimeModeLabelMap = map[AIAgentRuntimeMode]string{ - AIAgentRuntimeModeBuiltinGraph: "内置 Graph", - AIAgentRuntimeModeWorkflow: "会话流程", -} - -func GetAIAgentRuntimeModeLabel(mode AIAgentRuntimeMode) string { - return aiAgentRuntimeModeLabelMap[mode] -} diff --git a/internal/services/ai_agent_service.go b/internal/services/ai_agent_service.go index 4da0f42..0eaf602 100644 --- a/internal/services/ai_agent_service.go +++ b/internal/services/ai_agent_service.go @@ -229,7 +229,6 @@ func (s *aIAgentService) buildAIAgentModel(id int64, req request.CreateAIAgentRe SkillIDs: utils.JoinInt64s(skillIDs), AllowedMCPTools: directToolsJSON, AllowedGraphTools: graphToolsJSON, - RuntimeMode: enums.AIAgentRuntimeModeBuiltinGraph, WorkflowVersionID: 0, }, nil } @@ -357,26 +356,6 @@ func (s *aIAgentService) normalizeGraphTools(input []string) ([]string, error) { return ret, nil } -func (s *aIAgentService) normalizeRuntimeMode(input enums.AIAgentRuntimeMode, workflowVersionID int64) (enums.AIAgentRuntimeMode, int64, error) { - if input == 0 { - input = enums.AIAgentRuntimeModeBuiltinGraph - } - if !slices.Contains(enums.AIAgentRuntimeModeValues, input) { - return 0, 0, errorsx.InvalidParam("invalid ai agent runtime mode") - } - if input != enums.AIAgentRuntimeModeWorkflow { - return input, 0, nil - } - if workflowVersionID <= 0 { - return 0, 0, errorsx.InvalidParam("workflow version is required") - } - version := AIWorkflowService.GetVersion(workflowVersionID) - if version == nil || version.Status != enums.StatusOk { - return 0, 0, errorsx.InvalidParam("workflow version does not exist") - } - return input, workflowVersionID, nil -} - func (s *aIAgentService) UpdateSort(ids []int64) error { return sqls.WithTransaction(func(ctx *sqls.TxContext) error { for i, id := range ids { diff --git a/internal/services/ai_agent_workflow_service_test.go b/internal/services/ai_agent_workflow_service_test.go index 47a4c3d..e52b983 100644 --- a/internal/services/ai_agent_workflow_service_test.go +++ b/internal/services/ai_agent_workflow_service_test.go @@ -99,9 +99,6 @@ func TestAIWorkflowServicePublishAgentWorkflowBindsAgentVersion(t *testing.T) { if storedAgent == nil { t.Fatalf("expected stored agent") } - if storedAgent.RuntimeMode != enums.AIAgentRuntimeModeWorkflow { - t.Fatalf("expected agent runtime workflow, got %d", storedAgent.RuntimeMode) - } if storedAgent.WorkflowVersionID != version.ID { t.Fatalf("expected agent workflow version %d, got %d", version.ID, storedAgent.WorkflowVersionID) } diff --git a/internal/services/ai_workflow_service.go b/internal/services/ai_workflow_service.go index da268a9..3771b7f 100644 --- a/internal/services/ai_workflow_service.go +++ b/internal/services/ai_workflow_service.go @@ -301,7 +301,6 @@ func (s *aiWorkflowService) PublishAgentWorkflow(req request.PublishAIWorkflowRe return err } return repositories.AIAgentRepository.Updates(ctx.Tx, req.AgentID, map[string]any{ - "runtime_mode": enums.AIAgentRuntimeModeWorkflow, "workflow_version_id": version.ID, "update_user_id": operator.UserID, "update_user_name": operator.Username, diff --git a/web/app/dashboard/ai-agents/_components/config-workbench.tsx b/web/app/dashboard/ai-agents/_components/config-workbench.tsx index ca63476..acfeb42 100644 --- a/web/app/dashboard/ai-agents/_components/config-workbench.tsx +++ b/web/app/dashboard/ai-agents/_components/config-workbench.tsx @@ -836,10 +836,6 @@ export function AIAgentConfigWorkbench({ Agent 状态 {agent?.statusName || "-"} -
- 运行模式 - {agent?.runtimeModeName || "-"} -
生效流程版本 diff --git a/web/lib/api/admin.ts b/web/lib/api/admin.ts index 47f3b5c..0da8b59 100644 --- a/web/lib/api/admin.ts +++ b/web/lib/api/admin.ts @@ -242,8 +242,6 @@ export type AIAgent = { arguments?: Record }[] graphTools: string[] - runtimeMode: number - runtimeModeName: string workflowVersionId: number sortNo: number createdAt: string