feat: 主 agent set_goals 加目标时给 planner 记「人新增了目标」触发(批量感知)

- 新增 TriggerEvent{Kind:"goal", Goals:[]string} + Task.NotifyGoal([]string):
  一次 set_goals(不论单条/数组)合并成一条触发,planner 下轮开头据 len 渲染
  「人新增了一个目标:X」或「人新增了 N 个目标:A;B;C」,不再靠翻 goals 列表发现。
- set_goals 工具:addOneGoal 退化为纯落库;唤醒/触发/复活挪到整批写完后统一做
  (notifyGoal(addedTexts) 一次 + resumeTask 一次)。仅 mainagent 接 notifyGoal;
  拆解器/worker 退回纯 notify,round-0 不受影响。
- 复活场景顺序仍成立:goal 触发先入队(终态门在 drain 之前不会吞),resumeTask
  置 running 后那一轮才 drain 渲染。mainagent.Chat 加 notifyGoal 入参。
This commit is contained in:
Autumn-27 committed 2026-08-17 09:12:25 -04:00
1 parent 3c81d3d248
commit 8e03043548
5 files changed
+63 -19

No files matched your search

+16
View File
@@ -718,6 +718,22 @@ func (t *Task) NotifyFinding(intentID int64, summary string) {
t.Notify()
}
// NotifyGoal records that one OR MORE goals were added in a single set_goals call —
// by the human via the main agent — then wakes the planner, so the next round spells
// out "人新增了 N 个目标:…" instead of the planner having to spot new open goals in
// the overview. One call → one trigger event (set_goals 的一次批量算一条,不逐条刷屏).
// The event survives an early-returning terminal round (drain happens after the gate),
// so a set_goals that revives a done task still surfaces it once the task is running.
func (t *Task) NotifyGoal(texts []string) {
if len(texts) == 0 {
return
}
t.trigMu.Lock()
t.pendingTriggers = append(t.pendingTriggers, agent.TriggerEvent{Kind: "goal", Goals: texts})
t.trigMu.Unlock()
t.Notify()
}
// drainTriggers returns and clears the trigger events accumulated since the last round.
func (t *Task) drainTriggers() []agent.TriggerEvent {
t.trigMu.Lock()
+1 -1
View File
@@ -2053,7 +2053,7 @@ func (s *Server) chat(w http.ResponseWriter, r *http.Request) {
emit := func(rec db.Activity) { s.engine.emitActivity(t, rec) }
maTaskID, _ := strconv.ParseInt(t.ID, 10, 64)
resume := func() { s.resumeTaskForGoal(t) } // set_goals 新增目标 → 把任务拉回 running
if _, err := ma.Chat(ctx, maTaskID, s.m.Assets(), t.Store, t.Goal, req.Message, emit, t.Notify, resume); err != nil && ctx.Err() == nil {
if _, err := ma.Chat(ctx, maTaskID, s.m.Assets(), t.Store, t.Goal, req.Message, emit, t.Notify, resume, t.NotifyGoal); err != nil && ctx.Err() == nil {
s.engine.emitActivity(t, db.Activity{Worker: "mainagent", Kind: "text", IsError: true, Summary: "(主 Agent 出错:" + err.Error() + ")"})
}
}()