fix(scheduler): 事件水位每 tick 都推进,避免新建触发器回放历史
原来 fire{Findings,Goals,TaskTimeouts,TaskCreates,ToolCalls} 在没有
对应触发器时直接 return,不推进水位。于是水位会一直停在旧值;等用户
新建/启用触发器(如预置的 reporter on_tool_call),下一个 tick 就把
水位之后的全部历史事件当成新事件触发一遍(逐条唤起 reporter 写报告)。
改为:即便当前没有对应触发器,也照常把水位推进到最新(静默消费),
触发动作只在存在触发器时执行。这样触发器只对启用之后出现的事件生效,
不再回放历史。goal 用 fired-set 同理:无触发器时也标记为已消费。
This commit is contained in:
1 parent
e67ff26e90
commit
5244500fee
1 file changed
+23
-15
+23
-15
@@ -155,19 +155,22 @@ func (sc *Scheduler) fireFindings(triggers []*db.AgentTrigger) {
|
||||
want = append(want, tr)
|
||||
}
|
||||
}
|
||||
if len(want) == 0 {
|
||||
return
|
||||
}
|
||||
last, _ := strconv.ParseInt(sc.mustState(schedKeyLastFinding), 10, 64)
|
||||
events, err := sc.pg.NewFindingsSince(last)
|
||||
if err != nil || len(events) == 0 {
|
||||
return
|
||||
}
|
||||
// Advance the watermark whether or not any on_finding trigger is active: a
|
||||
// finding fires only for triggers live at the moment it appears. Otherwise a
|
||||
// trigger enabled later would replay the entire historical backlog at once.
|
||||
maxID := last
|
||||
for _, e := range events {
|
||||
if e.NodeID > maxID {
|
||||
maxID = e.NodeID
|
||||
}
|
||||
if len(want) == 0 {
|
||||
continue
|
||||
}
|
||||
msgCtx := fmt.Sprintf("\n\n【本次由任务发现 finding 触发】\n任务: #%d %s(目标:%s)\n发现: [%s/%s] %s",
|
||||
e.TaskID, e.TaskDesc, e.TaskGoal, e.VulnClass, e.Severity, e.Summary)
|
||||
for _, tr := range want {
|
||||
@@ -185,13 +188,12 @@ func (sc *Scheduler) fireGoals(triggers []*db.AgentTrigger) {
|
||||
want = append(want, tr)
|
||||
}
|
||||
}
|
||||
if len(want) == 0 {
|
||||
return
|
||||
}
|
||||
events, err := sc.pg.MetGoals()
|
||||
if err != nil || len(events) == 0 {
|
||||
return
|
||||
}
|
||||
// Mark goals as consumed whether or not a trigger is active, so enabling an
|
||||
// on_goal_met trigger later doesn't replay every already-met goal.
|
||||
fired := sc.firedGoalSet()
|
||||
changed := false
|
||||
for _, e := range events {
|
||||
@@ -200,6 +202,9 @@ func (sc *Scheduler) fireGoals(triggers []*db.AgentTrigger) {
|
||||
}
|
||||
fired[e.NodeID] = true
|
||||
changed = true
|
||||
if len(want) == 0 {
|
||||
continue
|
||||
}
|
||||
msgCtx := fmt.Sprintf("\n\n【本次由任务完成目标触发】\n任务: #%d %s(目标:%s)\n达成目标: %s",
|
||||
e.TaskID, e.TaskDesc, e.TaskGoal, e.Summary)
|
||||
for _, tr := range want {
|
||||
@@ -220,19 +225,20 @@ func (sc *Scheduler) fireTaskTimeouts(triggers []*db.AgentTrigger) {
|
||||
want = append(want, tr)
|
||||
}
|
||||
}
|
||||
if len(want) == 0 {
|
||||
return
|
||||
}
|
||||
last, _ := strconv.ParseInt(sc.mustState(schedKeyLastTimeout), 10, 64)
|
||||
events, err := sc.pg.TimedOutTasksSince(last)
|
||||
if err != nil || len(events) == 0 {
|
||||
return
|
||||
}
|
||||
// Advance the watermark even with no active trigger — see fireFindings.
|
||||
maxID := last
|
||||
for _, e := range events {
|
||||
if e.NodeID > maxID {
|
||||
maxID = e.NodeID
|
||||
}
|
||||
if len(want) == 0 {
|
||||
continue
|
||||
}
|
||||
msgCtx := fmt.Sprintf("\n\n【本次由任务超时触发】\n任务: #%d %s(目标:%s)",
|
||||
e.TaskID, e.TaskDesc, e.TaskGoal)
|
||||
for _, tr := range want {
|
||||
@@ -251,19 +257,20 @@ func (sc *Scheduler) fireTaskCreates(triggers []*db.AgentTrigger) {
|
||||
want = append(want, tr)
|
||||
}
|
||||
}
|
||||
if len(want) == 0 {
|
||||
return
|
||||
}
|
||||
last, _ := strconv.ParseInt(sc.mustState(schedKeyLastTaskCreate), 10, 64)
|
||||
events, err := sc.pg.NewTasksSince(last)
|
||||
if err != nil || len(events) == 0 {
|
||||
return
|
||||
}
|
||||
// Advance the watermark even with no active trigger — see fireFindings.
|
||||
maxID := last
|
||||
for _, e := range events {
|
||||
if e.NodeID > maxID {
|
||||
maxID = e.NodeID
|
||||
}
|
||||
if len(want) == 0 {
|
||||
continue
|
||||
}
|
||||
msgCtx := fmt.Sprintf("\n\n【本次由任务创建触发】\n任务ID: #%d\n任务描述: %s\n任务目标: %s",
|
||||
e.TaskID, e.TaskDesc, e.TaskGoal)
|
||||
for _, tr := range want {
|
||||
@@ -283,19 +290,20 @@ func (sc *Scheduler) fireToolCalls(triggers []*db.AgentTrigger) {
|
||||
want = append(want, tr)
|
||||
}
|
||||
}
|
||||
if len(want) == 0 {
|
||||
return
|
||||
}
|
||||
last, _ := strconv.ParseInt(sc.mustState(schedKeyLastToolCall), 10, 64)
|
||||
events, err := sc.pg.NewToolCallsSince(last)
|
||||
if err != nil || len(events) == 0 {
|
||||
return
|
||||
}
|
||||
// Advance the watermark even with no active trigger — see fireFindings.
|
||||
maxID := last
|
||||
for _, e := range events {
|
||||
if e.NodeID > maxID {
|
||||
maxID = e.NodeID
|
||||
}
|
||||
if len(want) == 0 {
|
||||
continue
|
||||
}
|
||||
errTag := ""
|
||||
if e.ToolIsErr {
|
||||
errTag = "[error] "
|
||||
|
||||
Reference in new issue
Block a user