Run scheduled tasks through workflows
This commit is contained in:
+15
-46
@@ -20,20 +20,10 @@ func (m *Manager) SaveSchedule(ctx context.Context, projectID, scheduleID string
|
||||
return api.Schedule{}, err
|
||||
}
|
||||
sc.Prompt = strings.TrimSpace(deref(save.Prompt))
|
||||
sc.Model = strings.TrimSpace(deref(save.Model))
|
||||
sc.Workflow = strings.TrimSpace(deref(save.Workflow))
|
||||
switch {
|
||||
case sc.Workflow != "" && sc.Model != "":
|
||||
return api.Schedule{}, errModelWithWorkflow
|
||||
case sc.Workflow == "" && sc.Prompt == "":
|
||||
return api.Schedule{}, fmt.Errorf("%w: prompt is required without a workflow", ErrInvalid)
|
||||
case sc.Workflow == "" && sc.Model == "":
|
||||
return api.Schedule{}, fmt.Errorf("%w: model is required without a workflow", ErrInvalid)
|
||||
case sc.Workflow != "":
|
||||
_, err = m.store.GetWorkflow(ctx, sc.Workflow)
|
||||
if err != nil {
|
||||
return api.Schedule{}, err
|
||||
}
|
||||
sc.Workflow = strings.TrimSpace(save.Workflow)
|
||||
_, err = m.store.GetWorkflow(ctx, sc.Workflow)
|
||||
if err != nil {
|
||||
return api.Schedule{}, err
|
||||
}
|
||||
|
||||
if scheduleID != "" {
|
||||
@@ -118,19 +108,8 @@ func (m *Manager) startScheduled(ctx context.Context, sc api.Schedule) error {
|
||||
if user.GitName == "" || user.GitEmail == "" {
|
||||
return ErrNoGitIdentity
|
||||
}
|
||||
if sc.Workflow != "" {
|
||||
_, err = m.StartWorkflow(ctx, project, user, sc.Title, project.DefaultBranch, "byre", sc.Workflow, sc.Prompt, nil, "")
|
||||
return err
|
||||
}
|
||||
task, err := m.CreateTask(ctx, project, sc.Title, user.Login, project.DefaultBranch, "byre")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = m.create(ctx, task, user, "", sc.Prompt, sc.Model, "byre", "", "", nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("task %s created, but its agent did not start: %w", task.Id, err)
|
||||
}
|
||||
return nil
|
||||
_, err = m.StartWorkflow(ctx, project, user, sc.Title, project.DefaultBranch, "byre", sc.Workflow, sc.Prompt, nil, "")
|
||||
return err
|
||||
}
|
||||
|
||||
func scheduleText(sc api.Schedule) string {
|
||||
@@ -150,22 +129,17 @@ func scheduleText(sc api.Schedule) string {
|
||||
default:
|
||||
fmt.Fprintf(b, " at %02d:%02d", sc.Hour, sc.Minute)
|
||||
}
|
||||
fmt.Fprintf(b, ", next run %s", sc.NextRun.Local().Format(time.RFC3339))
|
||||
if sc.Workflow != "" {
|
||||
fmt.Fprintf(b, ", workflow %q", sc.Workflow)
|
||||
} else {
|
||||
fmt.Fprintf(b, ", model %s", sc.Model)
|
||||
}
|
||||
fmt.Fprintf(b, ", next run %s, workflow %q", sc.NextRun.Local().Format(time.RFC3339), sc.Workflow)
|
||||
if sc.Prompt != "" {
|
||||
fmt.Fprintf(b, "\n prompt: %s", clip(sc.Prompt, 500))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (m *Manager) scheduleTools(l *live, tool func(name, description, schema string, run func(ctx context.Context, user api.User, raw json.RawMessage) (string, error)) mcp.Tool) []mcp.Tool {
|
||||
func (m *Manager) scheduleTools(tool func(name, description, schema string, run func(ctx context.Context, user api.User, raw json.RawMessage) (string, error)) mcp.Tool) []mcp.Tool {
|
||||
return []mcp.Tool{
|
||||
tool("list_schedules",
|
||||
"List the schedules: each one's id, project, owner, title, timing, model or workflow, prompt, and next run in the server's local time. Give project_id for one project's.",
|
||||
"List the schedules: each one's id, project, owner, title, timing, workflow, prompt, and next run in the server's local time. Give project_id for one project's.",
|
||||
`{"type": "object", "properties": {"project_id": {"type": "string"}}}`,
|
||||
func(ctx context.Context, user api.User, raw json.RawMessage) (string, error) {
|
||||
args := struct {
|
||||
@@ -190,25 +164,24 @@ func (m *Manager) scheduleTools(l *live, tool func(name, description, schema str
|
||||
}),
|
||||
|
||||
tool("save_schedule",
|
||||
"Create a schedule, or with schedule_id replace one's settings (project_id is then ignored). On each run byre creates a task in the project from its default branch, as create_task does, "+
|
||||
"as the schedule's owner (you, for one you create), and you get its created signal. Times are the server's local time. "+
|
||||
"Create a schedule, or with schedule_id replace one's settings (project_id is then ignored). On each run byre starts the workflow in the project from its default branch, as create_task with workflow does, "+
|
||||
"as the schedule's owner (you, for one you create). Times are the server's local time. "+
|
||||
"every hour runs at minute past each hour (hour 0); day at hour:minute; week at hour:minute on each of weekdays; month at hour:minute on day_of_month, or the month's last day when shorter. "+
|
||||
"weekdays only for week, day_of_month only for month. Each run's agent sees nothing else, so the prompt must be a complete brief. "+
|
||||
"With workflow, each run starts that workflow, prompt is optional and is its brief, and model can't be given; the workflow is looked up by name at each run. "+
|
||||
"weekdays only for week, day_of_month only for month. prompt is optional and is added to every stage's first message as the run's brief. "+
|
||||
"The workflow is looked up by name at each run. "+
|
||||
"A run missed while byre was down happens once when it starts. The human sees and edits schedules on the project's dashboard. Only when the human asks.",
|
||||
`{"type": "object", "properties": {
|
||||
"project_id": {"type": "string"},
|
||||
"schedule_id": {"type": "string"},
|
||||
"title": {"type": "string", "description": "The title of each task it creates."},
|
||||
"title": {"type": "string", "description": "The title of each run."},
|
||||
"every": {"type": "string", "enum": ["hour", "day", "week", "month"]},
|
||||
"weekdays": {"type": "array", "items": {"type": "string", "enum": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]}},
|
||||
"hour": {"type": "integer", "minimum": 0, "maximum": 23},
|
||||
"minute": {"type": "integer", "minimum": 0, "maximum": 59},
|
||||
"day_of_month": {"type": "integer", "minimum": 1, "maximum": 31},
|
||||
"prompt": {"type": "string"},
|
||||
"model": {"type": "string", "description": "Without workflow, the agent's model; defaults to yours."},
|
||||
"workflow": {"type": "string", "description": "The name of a workflow for each run to freeze a copy of and run."}
|
||||
}, "required": ["title", "every", "hour", "minute"]}`,
|
||||
}, "required": ["title", "every", "hour", "minute", "workflow"]}`,
|
||||
func(ctx context.Context, user api.User, raw json.RawMessage) (string, error) {
|
||||
args := struct {
|
||||
ProjectID string `json:"project_id"`
|
||||
@@ -223,10 +196,6 @@ func (m *Manager) scheduleTools(l *live, tool func(name, description, schema str
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if deref(save.Workflow) == "" {
|
||||
model := m.modelOr(deref(save.Model), l)
|
||||
save.Model = &model
|
||||
}
|
||||
sc, err := m.SaveSchedule(ctx, args.ProjectID, args.ScheduleID, save, user.Login, leadActor(user.Login))
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
Reference in New Issue
Block a user