feat(agent): trigger agent on member comment (on_comment trigger)

When a member comments on an issue assigned to an agent, automatically
enqueue a new task if the agent has on_comment trigger enabled (or no
triggers configured). Combined with session persistence, the agent
resumes its prior conversation context and sees the new feedback.

- Add HasActiveTaskForIssue query to prevent duplicate task enqueue
- Refactor shouldEnqueueAgentTask into reusable isAgentTriggerEnabled
- Add shouldEnqueueOnComment with active-task and status guards
- Call trigger logic from CreateComment handler
This commit is contained in:
Jiayuan 2026-03-29 17:01:19 +08:00
parent 5b2c61cfab
commit 32f795e1ef
2 changed files with 35 additions and 1 deletions

View file

@ -125,6 +125,14 @@ func (h *Handler) CreateComment(w http.ResponseWriter, r *http.Request) {
"issue_status": issue.Status,
})
// If the issue is assigned to an agent with on_comment trigger, enqueue a new task.
// The agent will resume its prior session and see this comment.
if h.shouldEnqueueOnComment(r.Context(), issue) {
if _, err := h.TaskService.EnqueueTaskForIssue(r.Context(), issue); err != nil {
slog.Warn("enqueue agent task on comment failed", "issue_id", issueID, "error", err)
}
}
writeJSON(w, http.StatusCreated, resp)
}

View file

@ -375,6 +375,32 @@ func (h *Handler) shouldEnqueueAgentTask(ctx context.Context, issue db.Issue) bo
if issue.Status != "todo" {
return false
}
return h.isAgentTriggerEnabled(ctx, issue, "on_assign")
}
// shouldEnqueueOnComment returns true if a member comment on this issue should
// trigger the assigned agent. Conditions: issue is assigned to an agent, the
// agent has on_comment trigger enabled, and no task is already active.
func (h *Handler) shouldEnqueueOnComment(ctx context.Context, issue db.Issue) bool {
// Don't trigger on terminal statuses.
if issue.Status == "done" || issue.Status == "cancelled" {
return false
}
if !h.isAgentTriggerEnabled(ctx, issue, "on_comment") {
return false
}
// Don't enqueue if there's already an active task for this issue.
hasActive, err := h.Queries.HasActiveTaskForIssue(ctx, issue.ID)
if err != nil || hasActive {
return false
}
return true
}
// isAgentTriggerEnabled checks if an issue is assigned to an agent with a
// specific trigger type enabled. Returns true if the agent has no triggers
// configured (default-enabled behavior).
func (h *Handler) isAgentTriggerEnabled(ctx context.Context, issue db.Issue, triggerType string) bool {
if !issue.AssigneeType.Valid || issue.AssigneeType.String != "agent" || !issue.AssigneeID.Valid {
return false
}
@ -392,7 +418,7 @@ func (h *Handler) shouldEnqueueAgentTask(ctx context.Context, issue db.Issue) bo
return false
}
for _, trigger := range triggers {
if trigger.Type == "on_assign" && trigger.Enabled {
if trigger.Type == triggerType && trigger.Enabled {
return true
}
}