diff --git a/server/scheduler.go b/server/scheduler.go index 1aeeb17..01fb6d1 100644 --- a/server/scheduler.go +++ b/server/scheduler.go @@ -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] "