feat: 新增主动拉取与多类型回调功能

- 新增 ActivePull 实体、DAO、DTO 及 Service,支持主动拉取任务管理
- 新增 ComposeCallback、VideoCallback、HttpNodeCallback 多类型回调接口
- FlowExecution 增加 NodeGroupId 和 TotalTokens 字段,支持节点组追踪与 Token 统计
- ExecutedNodes 结构由字符串列表改为包含执行状态的节点对象列表
- 重构回调通知机制,统一 Notify 函数调用
- 优化输出项类型判断逻辑,新增文件类型标识
This commit is contained in:
2026-06-10 14:23:55 +08:00
parent ab3a2d967e
commit 03c95c3601
33 changed files with 3207 additions and 615 deletions

View File

@@ -0,0 +1,99 @@
package node
import (
"ai-agent/workflow/consts/public"
nodeDto "ai-agent/workflow/model/dto/node"
"ai-agent/workflow/model/entity"
"context"
"gitea.com/red-future/common/db/gfdb"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
)
var NodeExecutionDao = &nodeExecutionDao{}
type nodeExecutionDao struct{}
// Insert 插入节点执行记录
func (d *nodeExecutionDao) Insert(ctx context.Context, req *nodeDto.CreateNodeExecutionReq) (id int64, err error) {
nodeExecution := new(entity.NodeExecution)
err = gconv.Struct(req, &nodeExecution)
if err != nil {
return 0, err
}
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodeExecution).Insert(&nodeExecution)
if err != nil {
return 0, err
}
return r.LastInsertId()
}
// Update 更新节点执行记录
func (d *nodeExecutionDao) Update(ctx context.Context, req *nodeDto.UpdateNodeExecutionReq) (rows int64, err error) {
model := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodeExecution).OmitEmpty()
if !g.IsEmpty(req.CompletionTokens) {
model.Data(entity.NodeExecutionCol.CompletionTokens, &gdb.Counter{
Field: entity.NodeExecutionCol.CompletionTokens,
Value: gconv.Float64(req.CompletionTokens),
})
}
if !g.IsEmpty(req.PromptTokens) {
model.Data(entity.NodeExecutionCol.PromptTokens, &gdb.Counter{
Field: entity.NodeExecutionCol.PromptTokens,
Value: gconv.Float64(req.PromptTokens),
})
}
if !g.IsEmpty(req.TotalTokens) {
model.Data(entity.NodeExecutionCol.TotalTokens, &gdb.Counter{
Field: entity.NodeExecutionCol.TotalTokens,
Value: gconv.Float64(req.TotalTokens),
})
}
r, err := model.Data(&req).Where(entity.NodeExecutionCol.Id, req.Id).Update()
if err != nil {
return 0, err
}
return r.RowsAffected()
}
// Delete 删除节点执行记录
func (d *nodeExecutionDao) Delete(ctx context.Context, req *nodeDto.DeleteNodeExecutionReq) (rows int64, err error) {
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodeExecution).Where(entity.NodeExecutionCol.Id, req.Id).Delete()
if err != nil {
return 0, err
}
return r.RowsAffected()
}
// Get 根据ID查询节点执行记录
func (d *nodeExecutionDao) Get(ctx context.Context, req *nodeDto.GetNodeExecutionReq, fields ...string) (res *entity.NodeExecution, err error) {
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodeExecution).NoTenantId(ctx).OmitEmpty().
Where(entity.NodeExecutionCol.Id, req.Id).
Fields(fields).One()
if err != nil {
return nil, err
}
if r.IsEmpty() {
return nil, nil
}
err = r.Struct(&res)
return res, err
}
// ListByFlowExecutionId 查询指定流程执行下的所有节点执行记录
func (d *nodeExecutionDao) ListByFlowExecutionId(ctx context.Context, req *nodeDto.ListNodeExecutionByFlowReq, fields ...string) (res []*entity.NodeExecution, total int, err error) {
model := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodeExecution).NoTenantId(ctx).Fields(fields).OmitEmpty()
model.Where(entity.NodeExecutionCol.FlowExecutionId, req.FlowExecutionId)
model.OrderAsc(entity.NodeExecutionCol.CreatedAt)
if req.Page != nil {
model.Page(int(req.Page.PageNum), int(req.Page.PageSize))
}
r, total, err := model.AllAndCount(false)
if err != nil {
return nil, 0, err
}
err = r.Structs(&res)
return res, total, err
}

View File

@@ -0,0 +1,95 @@
package node
import (
"ai-agent/workflow/consts/public"
nodeDto "ai-agent/workflow/model/dto/node"
"ai-agent/workflow/model/entity"
"context"
"gitea.com/red-future/common/db/gfdb"
"github.com/gogf/gf/v2/util/gconv"
)
var NodePromptDao = &nodePromptDao{}
type nodePromptDao struct{}
// Insert 插入节点提示词
func (d *nodePromptDao) Insert(ctx context.Context, req *nodeDto.CreateNodePromptReq) (id int64, err error) {
nodePrompt := new(entity.NodePrompt)
err = gconv.Struct(req, &nodePrompt)
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodePrompt).Insert(&nodePrompt)
if err != nil {
return 0, err
}
return r.LastInsertId()
}
// Update 更新节点提示词
func (d *nodePromptDao) Update(ctx context.Context, req *nodeDto.UpdateNodePromptReq) (rows int64, err error) {
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodePrompt).OmitEmpty().Data(&req).Where(entity.NodePromptCol.Id, req.Id).Update()
if err != nil {
return 0, err
}
return r.RowsAffected()
}
// Delete 删除节点提示词
func (d *nodePromptDao) Delete(ctx context.Context, req *nodeDto.DeleteNodePromptReq) (rows int64, err error) {
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodePrompt).Where(entity.NodePromptCol.Id, req.Id).Delete()
if err != nil {
return 0, err
}
return r.RowsAffected()
}
// Get 根据ID查询节点提示词
func (d *nodePromptDao) Get(ctx context.Context, req *nodeDto.GetNodePromptReq, fields ...string) (res *entity.NodePrompt, err error) {
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodePrompt).NoTenantId(ctx).OmitEmpty().
Where(entity.NodePromptCol.Id, req.Id).
Where(entity.NodePromptCol.Prompt, req.Prompt).
Where(entity.NodePromptCol.Creator, req.Creator).
Fields(fields).One()
if err != nil {
return nil, err
}
if r.IsEmpty() {
return nil, nil
}
err = r.Struct(&res)
return res, err
}
// ListByOnlyCreator 查询仅当前创建人自己创建的提示词
func (d *nodePromptDao) ListByOnlyCreator(ctx context.Context, req *nodeDto.ListMyNodePromptReq, fields ...string) (res []*entity.NodePrompt, total int, err error) {
model := gfdb.DB(ctx, public.DbNameBlackDeacon).Model(ctx, public.TableNameNodePrompt).NoTenantId(ctx).Fields(fields).OmitEmpty()
model.Where(entity.NodePromptCol.Creator, req.Creator)
model.Where(entity.NodePromptCol.NodeType, req.NodeType)
model.OrderDesc(entity.NodePromptCol.CreatedAt)
if req.Page != nil {
model.Page(int(req.Page.PageNum), int(req.Page.PageSize))
}
r, total, err := model.AllAndCount(false)
if err != nil {
return nil, 0, err
}
err = r.Structs(&res)
return res, total, err
}
// ListByCreator 查询当前创建人的所有提示词(包含系统和用户)
func (d *nodePromptDao) ListByCreator(ctx context.Context, req *nodeDto.ListNodePromptReq, fields ...string) (res []*entity.NodePrompt, total int, err error) {
// 完整 SQL
sql := ` SELECT * FROM black_deacon_node_prompt WHERE (creator=? OR source_type=1) AND node_type=? AND "deleted_at" IS NULL ORDER BY created_at DESC `
queryParams := []interface{}{req.Creator, req.NodeType}
if req.Page != nil {
sql += " LIMIT ?,?"
queryParams = append(queryParams, req.Page.PageNum, req.Page.PageSize)
}
r, err := gfdb.DB(ctx, public.DbNameBlackDeacon).GetAll(ctx, sql, queryParams...)
if err != nil {
return nil, 0, err
}
err = r.Structs(&res)
return res, total, err
}