From f3b15696b30433be6d597deeb5f8870d0ba8ccd4 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Thu, 22 Oct 2026 17:37:16 -0700 Subject: [PATCH] Let the lead configure the iPhone Action button --- internal/agents/workflows.go | 40 ++++++++++++++++++++++++++++++++ internal/server/notifications.go | 21 ++--------------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/internal/agents/workflows.go b/internal/agents/workflows.go index 1f88fce..d34db32 100644 --- a/internal/agents/workflows.go +++ b/internal/agents/workflows.go @@ -51,6 +51,23 @@ func (m *Manager) SetReviewWorkflow(ctx context.Context, projectID, name, actor return m.store.SetReviewWorkflow(ctx, projectID, name, actor) } +func (m *Manager) SetQuickRun(ctx context.Context, login string, q api.QuickRun) (api.User, error) { + if (q.ProjectId == "") != (q.Workflow == "") { + return api.User{}, fmt.Errorf("%w: project_id and workflow are set together", ErrInvalid) + } + if q.ProjectId != "" { + _, err := m.store.GetProject(ctx, q.ProjectId) + if err != nil { + return api.User{}, fmt.Errorf("project %s: %w", q.ProjectId, err) + } + _, err = m.store.GetWorkflow(ctx, q.Workflow) + if err != nil { + return api.User{}, fmt.Errorf("workflow %q: %w", q.Workflow, err) + } + } + return m.store.UpdateQuickRun(ctx, login, q) +} + func reviewProblem(def api.WorkflowDefinition) error { for _, s := range workflow.Stages(def) { if s.Agents != nil { @@ -918,6 +935,29 @@ func (m *Manager) workflowTools(tool func(name, description, schema string, run return fmt.Sprintf("Project %s is audited with workflow %q.", p.Name, p.AuditWorkflow), nil }), + tool("set_action_button", + "Set the workflow the human's iPhone Action button starts, and the project it runs in: pressing the button opens byre for a prompt and starts that workflow with it as the brief. "+ + "Empty project_id and workflow turn it off. Only when the human asks.", + `{"type": "object", "properties": { + "project_id": {"type": "string"}, + "workflow": {"type": "string"} + }, "required": ["project_id", "workflow"]}`, + func(ctx context.Context, user api.User, raw json.RawMessage) (string, error) { + q := api.QuickRun{} + err := json.Unmarshal(raw, &q) + if err != nil { + return "", err + } + u, err := m.SetQuickRun(ctx, user.Login, q) + if err != nil { + return "", err + } + if u.QuickRun.Workflow == "" { + return "The Action button starts no workflow now.", nil + } + return fmt.Sprintf("The Action button starts workflow %q in project %s.", u.QuickRun.Workflow, u.QuickRun.ProjectId), nil + }), + tool("delete_workflow", "Delete a workflow from the server. Tasks that froze it keep their copy. Only when the human asks.", `{"type": "object", "properties": {"name": {"type": "string"}}, "required": ["name"]}`, diff --git a/internal/server/notifications.go b/internal/server/notifications.go index e41d3cf..5ebff8e 100644 --- a/internal/server/notifications.go +++ b/internal/server/notifications.go @@ -47,26 +47,9 @@ func (s *Server) UpdateQuickRun(w http.ResponseWriter, r *http.Request) { return } - if (req.ProjectId == "") != (req.Workflow == "") { - writeError(w, http.StatusBadRequest, errors.New("project_id and workflow are set together")) - return - } - if req.ProjectId != "" { - _, err := s.store.GetProject(r.Context(), req.ProjectId) - if err != nil { - writeStoreError(w, err) - return - } - _, err = s.store.GetWorkflow(r.Context(), req.Workflow) - if err != nil { - writeStoreError(w, err) - return - } - } - - u, err := s.store.UpdateQuickRun(r.Context(), actor(r), req) + u, err := s.agents.SetQuickRun(r.Context(), actor(r), req) if err != nil { - writeStoreError(w, err) + writeAgentError(w, err) return } writeJSON(w, http.StatusOK, u)