Start a new task from a closed task
This commit is contained in:
+64
-2
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -19,6 +20,13 @@ func (m *Manager) Fork(ctx context.Context, src api.Task, project api.Project, n
|
||||
return t, err
|
||||
}
|
||||
|
||||
func forkOrigin(t api.Task, from string) string {
|
||||
if t.ForkedAt == nil {
|
||||
return "continued from " + from
|
||||
}
|
||||
return fmt.Sprintf("forked from %s at snapshot %d", from, *t.ForkedAt)
|
||||
}
|
||||
|
||||
func forkTitle(src api.Task, n int) string {
|
||||
return fmt.Sprintf("%s (fork of #%d)", src.Title, n)
|
||||
}
|
||||
@@ -172,7 +180,7 @@ func (m *Manager) fork(ctx context.Context, src api.Task, project api.Project, n
|
||||
return api.Task{}, "", fmt.Errorf("%w: snapshot %d of task %s has no recorded agent message at or before it to fork the conversation from", ErrConflict, n, src.Id)
|
||||
}
|
||||
|
||||
t, err := m.createTask(ctx, project, api.Task{
|
||||
return m.forkSession(ctx, project, api.Task{
|
||||
Title: title,
|
||||
MergeTitle: src.MergeTitle,
|
||||
CreatedBy: creator.Login,
|
||||
@@ -181,7 +189,61 @@ func (m *Manager) fork(ctx context.Context, src api.Task, project api.Project, n
|
||||
ForkedAt: &n,
|
||||
WorkflowStage: src.WorkflowStage,
|
||||
ParentTaskId: src.ParentTaskId,
|
||||
}, snap.CommitSha, creator.Login)
|
||||
}, snap.CommitSha, creator, srcSess, at)
|
||||
}
|
||||
|
||||
func (m *Manager) Continue(ctx context.Context, srcSess api.AgentSession, src api.Task, project api.Project, creator api.User, text, model, sendID, client string, images ...string) (api.Task, error) {
|
||||
if creator.GitName == "" || creator.GitEmail == "" {
|
||||
return api.Task{}, ErrNoGitIdentity
|
||||
}
|
||||
if src.Status == api.TaskStatusActive {
|
||||
return api.Task{}, fmt.Errorf("%w: task %s is still active", ErrConflict, src.Id)
|
||||
}
|
||||
if srcSess.Role != api.Implementer {
|
||||
return api.Task{}, fmt.Errorf("%w: session %s is a %s, not a task's agent", ErrConflict, srcSess.Id, srcSess.Role)
|
||||
}
|
||||
if srcSess.Vendor == api.Antigravity {
|
||||
return api.Task{}, fmt.Errorf("%w: session %s ran on Antigravity, and agy can't fork a conversation", ErrConflict, srcSess.Id)
|
||||
}
|
||||
|
||||
unlock := m.lockDelivery("continue:" + srcSess.Id)
|
||||
defer unlock()
|
||||
ctx = context.WithoutCancel(ctx)
|
||||
prior, sent, err := m.priorSend(ctx, sendID)
|
||||
if err != nil {
|
||||
return api.Task{}, err
|
||||
}
|
||||
if sent {
|
||||
return m.store.GetTask(ctx, prior.TaskId)
|
||||
}
|
||||
|
||||
events, err := m.store.TaskEvents(ctx, src.Id, 0, -1)
|
||||
if err != nil {
|
||||
return api.Task{}, err
|
||||
}
|
||||
at := forkPoint(events, srcSess.Id, math.MaxInt64)
|
||||
if at == "" {
|
||||
return api.Task{}, fmt.Errorf("%w: session %s has no recorded agent message to continue the conversation from", ErrConflict, srcSess.Id)
|
||||
}
|
||||
|
||||
t, sessionID, err := m.forkSession(ctx, project, api.Task{
|
||||
Title: src.Title + " (continued)",
|
||||
MergeTitle: src.MergeTitle,
|
||||
CreatedBy: creator.Login,
|
||||
ForkedFrom: &src.Id,
|
||||
}, project.DefaultBranch, creator, srcSess, at)
|
||||
if err != nil {
|
||||
return api.Task{}, err
|
||||
}
|
||||
_, _, err = m.Message(ctx, sessionID, creator.Login, text, model, sendID, client, images...)
|
||||
if err != nil {
|
||||
return api.Task{}, fmt.Errorf("task %s created, but its agent did not start: %w", t.Id, err)
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (m *Manager) forkSession(ctx context.Context, project api.Project, task api.Task, base string, creator api.User, srcSess api.AgentSession, at string) (api.Task, string, error) {
|
||||
t, err := m.createTask(ctx, project, task, base, creator.Login)
|
||||
if err != nil {
|
||||
return api.Task{}, "", err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user