Files
ai-agent/workflow/consts/node/node_template.go
T
19904408334 cef837a35c feat: 支持工作流断点续跑并拆分错误信息存储
- 新增同会话+同工作流最近执行失败且参数一致时断点续跑逻辑
- exec_workflow/exec_chat 新增 error 字段存储原始错误,error_message 仅存友好提示
- 新增 UpdateExecChatReq 与 exec_chat_dao Update 方法
- 新增 GetLatestBySessionAndFlow 查询最近执行记录
- 修正 ListDates 分组与排序 SQL 表达式
- 新增 pipeline 配置结构,删除旧设计文档
2026-08-21 09:54:06 +08:00

494 lines
13 KiB
Go

package node
// NodeGroup 节点分组标识
type NodeGroup string
// NodeType 节点类型标识
type NodeType string
// 分组常量定义
const (
NodeGroupBase NodeGroup = "base"
NodeGroupSystem NodeGroup = "system"
)
// 节点类型常量定义
const (
NodeTypeStart NodeType = "__start__"
NodeTypeModel NodeType = "model"
NodeTypeDataMerge NodeType = "data_merge"
NodeTypeForm NodeType = "form"
NodeTypeSubFlow NodeType = "sub_flow"
NodeTypeHttp NodeType = "http"
NodeTypeSystemSum NodeType = "system_sum"
NodeTypeScriptTranscribe NodeType = "script_transcribe"
)
// NodeGroupMeta 节点分组元数据
type NodeGroupMeta struct {
Key NodeGroup `json:"key"` // 后端存储标识
Name string `json:"name"` // 前端展示中文名称
}
// NodeTypeMeta 节点元数据
type NodeTypeMeta struct {
Key NodeType `json:"key"` // 节点类型标识
Name string `json:"name"` // 节点中文名称
Group NodeGroup `json:"group"` // 所属分组
Sort int `json:"sort"` // UI排序字段
Desc string `json:"desc,omitempty"` // 可选:节点简介
PatchLayout bool `json:"patchLayout"`
IsMultiParameter bool `json:"isMultiParameter"`
BatchExecOption bool `json:"batchExecOption"`
PreToolOption []NodePresetField `json:"preToolOption"`
PostToolOption []NodePresetField `json:"postToolOption"`
IsSaveFileOption bool `json:"isSaveFileOption"`
FormConfigOption bool `json:"formConfigOption"`
ModelConfigOption bool `json:"modelConfigOption"`
SkillOption bool `json:"skillOption"`
PromptOption bool `json:"promptOption"`
NegativePromptOption bool `json:"negativePromptOption"`
PresetOption []NodePresetField `json:"presetOption"`
OutputField []NodeOutputField `json:"outputField"`
}
type NodeOutputField struct {
Field string `json:"field"`
Label string `json:"label"`
}
type NodePresetField struct {
Value string `json:"value"`
ValueSource []ValueSource `json:"valueSource"`
Field string `json:"field"`
Label string `json:"label"`
Type string `json:"type"`
IsFormField bool `json:"isFormField"`
Constraint FieldConstraint `json:"constraint"`
Required bool `json:"required"`
Options []SelectOption `json:"options"`
}
type ValueSource struct {
NodeId string `json:"nodeId"`
Field string `json:"field"`
Label string `json:"label"`
}
// FieldConstraint 字段约束
type FieldConstraint struct {
// 数字类型:int、float、double、string
Type string `json:"type" dc:"类型"`
Min any `json:"min" dc:"最小值"`
Max any `json:"max" dc:"最大值"`
}
type SelectOption struct {
Key string `json:"key"`
Value string `json:"value"`
Config []NodePresetField `json:"config"`
}
// NodeGroupTree 对外输出树形结构:分组 + 分组下所有节点
type NodeGroupTree struct {
Group NodeGroupMeta `json:"group"`
Nodes []NodeTypeMeta `json:"nodes"`
}
// ===================== 元数据集中注册区(英文标识+中文文案统一维护) =====================
var NodeGroupMetaList = []NodeGroupMeta{
{
Key: NodeGroupBase,
Name: "基础",
},
}
var NodeTypeMetaList = []NodeTypeMeta{
{
Key: NodeTypeModel,
Name: "模型",
Group: NodeGroupBase,
Sort: 1,
Desc: "模型调用节点,可配置模型参数、模型配置、技能、提示语、结果汇集、结果保存、结果返回、结果展示等信息。",
PatchLayout: true,
IsMultiParameter: true,
BatchExecOption: true,
PreToolOption: []NodePresetField{
{
Field: "perTool",
Label: "前置方法",
Type: "select",
Required: false,
Options: []SelectOption{},
},
},
PostToolOption: []NodePresetField{
{
Field: "postTool",
Label: "后置方法",
Type: "select",
Required: false,
Options: []SelectOption{},
},
},
IsSaveFileOption: true,
FormConfigOption: false,
ModelConfigOption: true,
SkillOption: false,
PromptOption: true,
NegativePromptOption: false,
},
{
Key: NodeTypeDataMerge,
Name: "结果汇集",
Group: NodeGroupBase,
Sort: 2,
Desc: "结果汇集节点,可配置结果汇集方式、结果保存、结果返回、结果展示等信息。",
IsMultiParameter: false,
BatchExecOption: false,
IsSaveFileOption: false,
FormConfigOption: false,
ModelConfigOption: false,
SkillOption: false,
PromptOption: false,
NegativePromptOption: false,
},
{
Key: NodeTypeForm,
Name: "表单",
Group: NodeGroupBase,
Sort: 3,
Desc: "表单节点,可配置表单字段、表单配置、结果汇集、结果保存、结果返回、结果展示等信息。",
IsMultiParameter: false,
BatchExecOption: false,
IsSaveFileOption: false,
FormConfigOption: true,
ModelConfigOption: false,
SkillOption: false,
PromptOption: false,
NegativePromptOption: false,
},
{
Key: NodeTypeSubFlow,
Name: "子流程",
Group: NodeGroupBase,
Sort: 4,
PresetOption: []NodePresetField{
{
Field: "maxConcurrency",
Label: "生成次数",
Type: "input",
Value: "1",
IsFormField: true,
Constraint: FieldConstraint{
Type: "int",
Min: 1,
Max: 10,
},
Required: true,
},
},
},
{
Key: NodeTypeHttp,
Name: "HTTP(S)接口",
Group: NodeGroupBase,
Sort: 5,
Desc: "HTTP(S)接口节点,可配置HTTP(S)接口地址、请求方式、请求头、请求体、结果返回结构、结果返回方式、结果返回结构、结果返回方式等信息。",
BatchExecOption: false,
IsSaveFileOption: true,
FormConfigOption: false,
ModelConfigOption: false,
SkillOption: false,
PromptOption: false,
NegativePromptOption: false,
PresetOption: []NodePresetField{
{
Field: "method",
Label: "请求方式",
Type: "select",
Required: true,
Options: []SelectOption{
{Key: "GET", Value: "GET"},
{Key: "POST", Value: "POST"},
},
},
{
Field: "url",
Label: "请求地址",
Type: "input",
Constraint: FieldConstraint{
Type: "string",
Min: 1,
Max: -1,
},
Required: true,
},
{
Field: "headers",
Label: "请求头(支持Authorization鉴权)",
Type: "keyValue",
Required: false,
},
{
Field: "bodyType",
Label: "请求体类型",
Type: "select",
Required: true,
Options: []SelectOption{
{Key: "None", Value: "无"},
{Key: "JSON", Value: "JSON"},
},
},
{
Field: "body",
Label: "请求体内容",
Type: "schemaJson",
Required: false,
},
{
Field: "response",
Label: "结果返回结构",
Type: "schemaJson",
Required: true,
},
{
Field: "responseType",
Label: "结果返回方式",
Type: "select",
Required: true,
Options: []SelectOption{
{Key: "sync", Value: "同步返回"},
{Key: "callback", Value: "等候回调", Config: []NodePresetField{
{
Field: "callbackUrl",
Label: "回调地址(只需要填写字段名称)",
Type: "input",
Constraint: FieldConstraint{
Type: "string",
Min: 1,
Max: -1,
},
Required: true,
},
}},
{Key: "pull", Value: "主动拉取", Config: []NodePresetField{
{
Field: "method",
Label: "请求方式",
Type: "select",
Required: true,
Options: []SelectOption{
{Key: "GET", Value: "GET"},
{Key: "POST", Value: "POST"},
},
},
{
Field: "url",
Label: "请求地址",
Type: "input",
Constraint: FieldConstraint{
Type: "string",
Min: 1,
Max: -1,
},
Required: true,
},
{
Field: "headers",
Label: "请求头(支持Authorization鉴权)",
Type: "keyValue",
Required: false,
},
{
Field: "bodyType",
Label: "请求体类型",
Type: "select",
Required: true,
Options: []SelectOption{
{Key: "None", Value: "无"},
{Key: "JSON", Value: "JSON"},
},
},
{
Field: "body",
Label: "请求体内容",
Type: "schemaJson",
Required: true,
},
{
Field: "response",
Label: "结果返回结构",
Type: "schemaJson",
Required: true,
},
}},
},
},
},
},
{
Key: NodeTypeScriptTranscribe,
Name: "脚本转写",
Group: NodeGroupBase,
Sort: 6,
Desc: "脚本转写节点,把文案/视频分析结果通过大模型转写为结构化分镜脚本([]Shot),作为视频生成节点的 shots 输入。",
IsMultiParameter: false,
BatchExecOption: false,
IsSaveFileOption: false,
FormConfigOption: false,
ModelConfigOption: true,
SkillOption: false,
PromptOption: false,
NegativePromptOption: false,
PresetOption: []NodePresetField{
{
Field: "totalDuration",
Label: "视频总时长",
Type: "input",
Constraint: FieldConstraint{
Type: "int",
Min: 1,
Max: 300,
},
Required: true,
},
{
Field: "modelId",
Label: "视频模型",
Type: "select",
Required: true,
Options: []SelectOption{},
},
},
OutputField: []NodeOutputField{
{
Field: "prompt",
Label: "转写内容",
},
{
Field: "duration",
Label: "时长",
},
{
Field: "seed",
Label: "种子",
},
{
Field: "reference_urls",
Label: "参考链接",
},
},
},
{
Key: NodeTypeSystemSum,
Name: "工作流内置节点-保存结果",
Group: NodeGroupSystem,
Sort: 7,
},
}
// ===================== 缓存map & 工具函数 =====================
var (
nodeTypeMetaMap map[NodeType]NodeTypeMeta
nodeGroupMap map[NodeGroup]NodeGroupMeta
)
func init() {
// 初始化分组缓存
nodeGroupMap = make(map[NodeGroup]NodeGroupMeta, len(NodeGroupMetaList))
for _, meta := range NodeGroupMetaList {
nodeGroupMap[meta.Key] = meta
}
// 初始化节点缓存
nodeTypeMetaMap = make(map[NodeType]NodeTypeMeta, len(NodeTypeMetaList))
for _, meta := range NodeTypeMetaList {
nodeTypeMetaMap[meta.Key] = meta
}
}
// GetNodeTypeMeta 根据节点类型获取元信息
func GetNodeTypeMeta(typ NodeType) (NodeTypeMeta, bool) {
meta, ok := nodeTypeMetaMap[typ]
return meta, ok
}
// GetNodeTypeName 快速获取节点中文名称,不存在返回原始key
func GetNodeTypeName(typ NodeType) string {
meta, ok := nodeTypeMetaMap[typ]
if !ok {
return string(typ)
}
return meta.Name
}
// GetNodeGroupMeta 根据分组标识获取分组元信息
func GetNodeGroupMeta(g NodeGroup) (NodeGroupMeta, bool) {
meta, ok := nodeGroupMap[g]
return meta, ok
}
// GetNodeGroupName 快速获取分组中文名称
func GetNodeGroupName(g NodeGroup) string {
meta, ok := nodeGroupMap[g]
if !ok {
return string(g)
}
return meta.Name
}
// GetAllNodeTypeMeta 返回全部节点元数据副本
func GetAllNodeTypeMeta() []NodeTypeMeta {
list := make([]NodeTypeMeta, len(NodeTypeMetaList))
copy(list, NodeTypeMetaList)
return list
}
// GetNodeGroupTree 获取【分组+节点】树形列表,完整所有节点
func GetNodeGroupTree() []NodeGroupTree {
return getFilteredNodeTree(nil)
}
// GetFilterNodeTree 根据指定分组过滤节点树形结构
// groups: 需要展示的分组key列表,传入nil返回全部
func GetFilterNodeTree(groups []NodeGroup) []NodeGroupTree {
return getFilteredNodeTree(groups)
}
// getFilteredNodeTree 内部通用树形构建逻辑
func getFilteredNodeTree(filterGroups []NodeGroup) []NodeGroupTree {
// 构建分组过滤集合
filterSet := make(map[NodeGroup]bool)
for _, g := range filterGroups {
filterSet[g] = true
}
groupNodeMap := make(map[NodeGroup][]NodeTypeMeta)
for _, node := range NodeTypeMetaList {
// 有过滤条件 && 当前分组不在过滤列表,则跳过
if len(filterSet) > 0 && !filterSet[node.Group] {
continue
}
groupNodeMap[node.Group] = append(groupNodeMap[node.Group], node)
}
var tree []NodeGroupTree
// 按定义顺序组装分组
for _, gMeta := range NodeGroupMetaList {
// 如果开启过滤,跳过不在筛选列表中的分组
if len(filterSet) > 0 && !filterSet[gMeta.Key] {
continue
}
nodes := groupNodeMap[gMeta.Key]
if len(nodes) == 0 {
continue
}
tree = append(tree, NodeGroupTree{
Group: gMeta,
Nodes: nodes,
})
}
return tree
}