Stop merge and discard nudges after discussion is indicated
This commit is contained in:
1 parent
b9fcca999e
commit
e31462281b
4 files changed
+35
-3
No files matched your search
@@ -905,7 +905,7 @@ func (m *Manager) startLive(ctx context.Context, sess api.AgentSession, task api
|
||||
return nil, err
|
||||
}
|
||||
l.notes = "\n\n" + taskNotesGuidance + "\n\n" + notes
|
||||
tools = append(tools, m.messageLeadTool(l), m.suggestNoteTool(l), m.readyForMergeTool(l), m.suggestDiscardTool(l), m.cancelReadyTool(l), m.respondToFindingTool(l))
|
||||
tools = append(tools, m.messageLeadTool(l), m.suggestNoteTool(l), m.setDiscussionTool(l), m.readyForMergeTool(l), m.suggestDiscardTool(l), m.cancelReadyTool(l), m.respondToFindingTool(l))
|
||||
if sess.Vendor == api.Claude {
|
||||
tools = append(tools, m.forkTool(l))
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
const readyPromptAsk = "If it isn't ready (work remains that you mean to do, or you're waiting on the human), call neither: say what's left in one line and end your turn. " +
|
||||
"If you're waiting on the human for a decision or input, ask it with ask_human now, even if an earlier message already put it in prose, so it reaches them. " +
|
||||
"If this task is only a discussion with the human (questions, explanations, advice, no work to land) and the discussion is still going, ignore this message: call none of these and end your turn with one line, so the discussion can continue. " +
|
||||
"If this task is a discussion with the human, call set_discussion with discussion=true to stop further completion nudges, then end your turn so the discussion can continue. When the discussion is over and the task is ready to finish, call set_discussion with discussion=false to enable completion nudges again, then call ready_for_merge or suggest_discard as appropriate. " +
|
||||
"If you already called ready_for_merge, suggest_discard or ask_human before this message, and it still applies, call it again now: only a call made after this message counts. Don't change any files this turn."
|
||||
|
||||
const readyPrompt = "Your turn has ended and the review of your latest work has finished. If the task is ready to merge, call ready_for_merge with an overview of the whole task, then end your turn with one line. " +
|
||||
@@ -38,6 +38,29 @@ func finishStagePrompt(frozen store.FrozenWorkflow, stage string) string {
|
||||
"If you're waiting on the human for a decision or input, ask it with ask_human and end your turn.", stage, frozen.Name, waiting)
|
||||
}
|
||||
|
||||
func (m *Manager) setDiscussionTool(l *live) mcp.Tool {
|
||||
return mcp.Tool{
|
||||
Name: "set_discussion",
|
||||
Description: "Set whether this task is a discussion. Every task starts with discussion off. Turn it on while discussing with the human to stop completion nudges. When the discussion is over and the task is ready to finish, turn it off again, then call ready_for_merge or suggest_discard as appropriate.",
|
||||
InputSchema: json.RawMessage(`{"type":"object","properties":{"discussion":{"type":"boolean","description":"True stops completion nudges; false enables them again."}},"required":["discussion"]}`),
|
||||
Handler: mcp.Typed(func(ctx context.Context, args struct {
|
||||
Discussion bool `json:"discussion"`
|
||||
}) (string, error) {
|
||||
err := m.store.SetTaskDiscussion(ctx, l.taskID, args.Discussion)
|
||||
if errors.Is(err, store.ErrNotFound) {
|
||||
return "", fmt.Errorf("%w: this task is closed", ErrConflict)
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if args.Discussion {
|
||||
return "Discussion on: completion nudges are stopped. When the discussion is over and the task is ready to finish, call set_discussion with discussion=false, then ready_for_merge or suggest_discard as appropriate.", nil
|
||||
}
|
||||
return "Discussion off: completion nudges are enabled again.", nil
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
type readyArgs struct {
|
||||
Overview string `json:"overview"`
|
||||
Merge api.TaskReadyMerge `json:"merge"`
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE tasks ADD COLUMN discussion INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -50,7 +50,7 @@ func readyPrompts(ctx context.Context, tx *sql.Tx, emit emitFunc) ([]ReadyPrompt
|
||||
WHERE l.task_id = tasks.id AND l.role != 'reviewer' AND l.state != 'completed'
|
||||
AND l.member = (SELECT f.member FROM agent_sessions f WHERE f.task_id = tasks.id AND f.role != 'reviewer' ORDER BY f.created_at LIMIT 1)
|
||||
ORDER BY l.created_at DESC LIMIT 1)
|
||||
WHERE tasks.status = 'active' AND tasks.state IN ('idle', 'finished', 'ready_to_merge', 'discard_suggested') AND s.state = 'idle'
|
||||
WHERE tasks.status = 'active' AND tasks.discussion = 0 AND tasks.state IN ('idle', 'finished', 'ready_to_merge', 'discard_suggested') AND s.state = 'idle'
|
||||
AND NOT EXISTS (SELECT 1 FROM inbox_items i WHERE i.task_id = tasks.id AND i.state = 'open')
|
||||
AND NOT EXISTS (SELECT 1 FROM task_inputs q WHERE q.task_id = tasks.id)
|
||||
AND EXISTS (SELECT 1 FROM events e WHERE e.task_id = tasks.id AND e.seq > tasks.ready_prompt_seq
|
||||
@@ -142,3 +142,11 @@ func readyPrompts(ctx context.Context, tx *sql.Tx, emit emitFunc) ([]ReadyPrompt
|
||||
}
|
||||
return prompts, nil
|
||||
}
|
||||
|
||||
// SetTaskDiscussion controls whether the coordinator nudges this task to finish.
|
||||
func (s *Store) SetTaskDiscussion(ctx context.Context, id string, discussion bool) error {
|
||||
return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
|
||||
_, err := updatedProject(ctx, tx, `UPDATE tasks SET discussion = ? WHERE id = ? AND status = 'active' RETURNING project_id`, discussion, id)
|
||||
return err
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user