- 新增计费模块:执行开始建单、终态结算/取消/失败处理,支持按条/按秒/按token计费 - 新增执行生命周期跟踪:优雅关停时取消运行中执行并等待落库 - 新增异步任务等待/通知机制(Wait/Notify) - 重构执行记录落库与进度上报,统一失败分类与重试语义 - 重命名文件:async_task.go→async.go、flow_checkpoint_store.go→exec_checkpoint.go、flow_graph_util.go→exec_record.go - 更新 .gitignore 与数据库密码配置
88 lines
2.0 KiB
Go
88 lines
2.0 KiB
Go
package flow
|
|
|
|
import (
|
|
"ai-agent/workflow/model/entity"
|
|
"net/url"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// FindEndNodes 从指定起始节点开始,遍历图找到所有末端节点(没有出边的节点)
|
|
func FindEndNodes(startNodeId string, edges []entity.FlowEdge) []string {
|
|
nextMap := make(map[string][]string)
|
|
for _, e := range edges {
|
|
nextMap[e.From] = append(nextMap[e.From], e.To)
|
|
}
|
|
|
|
endNodeSet := make(map[string]struct{})
|
|
visited := make(map[string]struct{})
|
|
queue := []string{startNodeId}
|
|
|
|
for len(queue) > 0 {
|
|
node := queue[0]
|
|
queue = queue[1:]
|
|
|
|
if _, exist := visited[node]; exist {
|
|
continue
|
|
}
|
|
visited[node] = struct{}{}
|
|
|
|
nextList := nextMap[node]
|
|
if len(nextList) == 0 {
|
|
endNodeSet[node] = struct{}{}
|
|
continue
|
|
}
|
|
queue = append(queue, nextList...)
|
|
}
|
|
|
|
res := make([]string, 0, len(endNodeSet))
|
|
for k := range endNodeSet {
|
|
res = append(res, k)
|
|
}
|
|
return res
|
|
}
|
|
|
|
// ExtractFlowNodeFrom 从 FlowInfo 中提取节点列表(返回指针切片)
|
|
func ExtractFlowNodeFrom(flowContent *entity.FlowInfo) []*entity.FlowNode {
|
|
var flowNodes []*entity.FlowNode
|
|
for _, item := range flowContent.Nodes {
|
|
flowNodes = append(flowNodes, &item)
|
|
}
|
|
return flowNodes
|
|
}
|
|
|
|
// GetFileTypeByPath 根据文件路径/URL的后缀名判断文件类型
|
|
func GetFileTypeByPath(filePath string) string {
|
|
if filePath == "" {
|
|
return ""
|
|
}
|
|
|
|
// 解析 URL,获取真实路径(兼容 http 链接)
|
|
u, err := url.Parse(filePath)
|
|
if err == nil {
|
|
filePath = u.Path
|
|
}
|
|
|
|
// 获取后缀(小写)
|
|
ext := filepath.Ext(filePath)
|
|
ext = strings.ToLower(ext)
|
|
|
|
// 判断类型
|
|
switch ext {
|
|
case ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp":
|
|
return "image"
|
|
case ".mp4", ".mov", ".avi", ".flv", ".wmv", ".mkv":
|
|
return "video"
|
|
case ".mp3", ".wav", ".m4a", ".flac", ".aac", ".ogg":
|
|
return "audio"
|
|
case ".txt", ".md", ".log", ".json", ".xml", ".inc":
|
|
return "text"
|
|
case ".html":
|
|
return "html"
|
|
case ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx":
|
|
return "document"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|