Review every new snapshot with an agent from the other vendor
This commit is contained in:
@@ -54,6 +54,8 @@ type Manager struct {
|
||||
mergeMu sync.Mutex
|
||||
mergeHolders map[string]string
|
||||
|
||||
reviewMu sync.Mutex
|
||||
|
||||
bad *badLines
|
||||
watchStop chan struct{}
|
||||
}
|
||||
@@ -69,6 +71,7 @@ type live struct {
|
||||
taskID string
|
||||
projectID string
|
||||
owner string
|
||||
reviewID string
|
||||
stopping bool
|
||||
interrupted bool
|
||||
asked bool
|
||||
@@ -84,6 +87,10 @@ type live struct {
|
||||
contextWindow int
|
||||
}
|
||||
|
||||
func (l *live) implementer() bool {
|
||||
return l.owner == "" && l.reviewID == ""
|
||||
}
|
||||
|
||||
func New(st *store.Store, worktreeRoot, leadRoot, codexHome string) *Manager {
|
||||
m := &Manager{
|
||||
store: st,
|
||||
@@ -274,7 +281,7 @@ func (m *Manager) Recover(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sess.Owner == "" {
|
||||
if sess.Role == api.Implementer {
|
||||
m.abandonMerge(task.Id, task.ProjectId)
|
||||
}
|
||||
continue
|
||||
@@ -296,6 +303,11 @@ func (m *Manager) Recover(ctx context.Context) error {
|
||||
m.logUndelivered(ctx, sess.Id, "idle at startup")
|
||||
}
|
||||
|
||||
err = m.recoverReviews(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go m.deliverAllLeads()
|
||||
go m.startHeldMerges(context.Background())
|
||||
return nil
|
||||
@@ -431,7 +443,7 @@ func (m *Manager) message(ctx context.Context, l *live, actor, text string, imag
|
||||
}
|
||||
|
||||
payload := map[string]any{"text": text}
|
||||
if l.owner == "" {
|
||||
if l.implementer() {
|
||||
head, err := git.Head(l.dir)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -503,6 +515,17 @@ func (m *Manager) ensureLive(ctx context.Context, sess api.AgentSession, task ap
|
||||
}
|
||||
tools := []mcp.Tool{m.askTool(l), m.cancelQuestionTool(l), m.createTaskTool(l), m.setMergeTitleTool(l), m.exposePortTool(l)}
|
||||
env := portEnv(task)
|
||||
if sess.Role == api.Reviewer {
|
||||
r, err := m.store.ReviewBySession(ctx, sess.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l.reviewID = r.Id
|
||||
l.dir = m.reviewDir(task.ProjectId, r.Id)
|
||||
g = reviewGuidance
|
||||
tools = []mcp.Tool{m.submitReviewTool(l)}
|
||||
env = nil
|
||||
}
|
||||
if l.owner != "" {
|
||||
l.dir = filepath.Join(m.leadRoot, url.PathEscape(l.owner))
|
||||
err = os.MkdirAll(l.dir, 0o755)
|
||||
@@ -563,6 +586,10 @@ func (m *Manager) pump(l *live) {
|
||||
if err != nil {
|
||||
slog.Error("record session exit", "session", l.id, "err", err)
|
||||
}
|
||||
if l.reviewID != "" {
|
||||
m.finishReviewer(l, "the reviewer's process exited mid-turn")
|
||||
return
|
||||
}
|
||||
if l.owner == "" {
|
||||
m.abandonMerge(l.taskID, l.projectID)
|
||||
m.fileError(l, "The agent process exited mid-turn. Send a message to resume it.")
|
||||
@@ -698,6 +725,9 @@ func (m *Manager) turnEnded(ctx context.Context, l *live, res endResult) error {
|
||||
if l.owner != "" {
|
||||
return m.leadTurnEnded(ctx, l, res)
|
||||
}
|
||||
if l.reviewID != "" {
|
||||
return m.reviewTurnEnded(ctx, l, res)
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
interrupted := l.interrupted
|
||||
|
||||
Reference in New Issue
Block a user