Bold questions
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
package agents
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"g.fc.run/misc/byre/internal/api"
|
||||
"g.fc.run/misc/byre/internal/git"
|
||||
"g.fc.run/misc/byre/internal/mcp"
|
||||
"g.fc.run/misc/byre/internal/store"
|
||||
)
|
||||
|
||||
func (m *Manager) CreateTask(ctx context.Context, project api.Project, title, createdBy, base string) (api.Task, error) {
|
||||
id := store.NewID()
|
||||
t := api.Task{
|
||||
Id: id,
|
||||
ProjectId: project.Id,
|
||||
Title: title,
|
||||
Branch: "byre/" + id,
|
||||
WorktreePath: filepath.Join(m.worktreeRoot, project.Id, id),
|
||||
Status: api.TaskStatusActive,
|
||||
CreatedBy: createdBy,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
}
|
||||
|
||||
var err error
|
||||
t.BaseRef, err = git.AddWorktree(project.RepoPath, t.WorktreePath, t.Branch, base)
|
||||
if err != nil {
|
||||
return api.Task{}, err
|
||||
}
|
||||
|
||||
err = m.store.CreateTask(ctx, t)
|
||||
if err != nil {
|
||||
return api.Task{}, err
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
type createTaskArgs struct {
|
||||
Title string `json:"title"`
|
||||
Prompt string `json:"prompt"`
|
||||
Base string `json:"base"`
|
||||
Model string `json:"model"`
|
||||
}
|
||||
|
||||
func (m *Manager) createTaskTool(l *live) mcp.Tool {
|
||||
return mcp.Tool{
|
||||
Name: "create_task",
|
||||
Description: "Create a new byre task in this project, with its own branch and worktree, and start an agent on it with prompt as its first message. " +
|
||||
"Use it to run independent pieces of work in parallel. The new agent sees nothing of your context, so the prompt must be a complete brief. " +
|
||||
"base picks the starting commit: default_branch starts from the project's default branch; this_task starts from this task's HEAD, " +
|
||||
"which includes your committed work but not uncommitted edits (byre commits at the end of each turn). " +
|
||||
"Returns at once with the new task's id; the new agent runs on its own.",
|
||||
InputSchema: json.RawMessage(`{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {"type": "string", "description": "Short task title, shown in the task list."},
|
||||
"prompt": {"type": "string", "description": "The new agent's first message: a complete, self-contained brief."},
|
||||
"base": {"type": "string", "enum": ["default_branch", "this_task"]},
|
||||
"model": {"type": "string", "description": "Model for the new agent. Defaults to this session's model."}
|
||||
},
|
||||
"required": ["title", "prompt", "base"]
|
||||
}`),
|
||||
Handler: func(ctx context.Context, raw json.RawMessage) (string, error) {
|
||||
return m.createTaskFromAgent(ctx, l, raw)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) createTaskFromAgent(ctx context.Context, l *live, raw json.RawMessage) (string, error) {
|
||||
args := createTaskArgs{}
|
||||
err := json.Unmarshal(raw, &args)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("malformed create_task call: %w", err)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(args.Title) == "" || strings.TrimSpace(args.Prompt) == "" {
|
||||
return "", errors.New("title and prompt are required")
|
||||
}
|
||||
|
||||
sess, err := m.store.GetSession(ctx, l.id)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
project, err := m.store.GetProject(ctx, l.projectID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
creator, err := m.store.GetUser(ctx, sess.CreatedBy)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
base := ""
|
||||
switch args.Base {
|
||||
case "default_branch":
|
||||
base = project.DefaultBranch
|
||||
case "this_task":
|
||||
base, err = git.Head(l.dir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("base must be default_branch or this_task, not %q", args.Base)
|
||||
}
|
||||
|
||||
model := args.Model
|
||||
if model == "" {
|
||||
model = sess.Model
|
||||
}
|
||||
|
||||
task, err := m.CreateTask(ctx, project, args.Title, creator.Login, base)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
_, err = m.create(ctx, task, creator, args.Prompt, model, agentActor)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("task %s created, but its agent did not start: %w", task.Id, err)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Task %s %q created from %s and its agent started.", task.Id, task.Title, task.BaseRef), nil
|
||||
}
|
||||
Reference in New Issue
Block a user