diff --git a/internal/agents/leadtools.go b/internal/agents/leadtools.go index cc9aadc..1a2bb33 100644 --- a/internal/agents/leadtools.go +++ b/internal/agents/leadtools.go @@ -518,15 +518,18 @@ func (m *Manager) leadTools(l *live) []mcp.Tool { } m.mu.Lock() working := m.paneFocus[user.Login].Focused || m.paneFocus[user.Login].Drafting - humanMoved := m.humanMoved[user.Login] - since := time.Since(humanMoved) + move := m.moveHolds[user.Login] + start := m.startHolds[user.Login] + since := time.Since(move.at) moveHeld := since < moveHold - startHeld := !moveHeld && time.Since(m.startedTodo[user.Login]) < startHold + startHeld := !moveHeld && time.Since(start.at) < startHold if moveHeld { - m.moveRefused[user.Login] = true + move.refused = true + m.moveHolds[user.Login] = move } if startHeld { - m.startRefused[user.Login] = true + start.refused = true + m.startHolds[user.Login] = start } m.mu.Unlock() if moveHeld { @@ -596,13 +599,12 @@ func (m *Manager) SetFocus(ctx context.Context, login string, f api.Focus, actor m.mu.Lock() m.paneMoved[login] = at if actor == login { - m.humanMoved[login] = at - delete(m.moveRefused, login) + m.moveHolds[login] = showHold{at: at} } m.mu.Unlock() if actor == login { time.AfterFunc(moveHold, func() { - err := m.endMoveHold(context.Background(), login, at) + err := m.endShowHold(context.Background(), login, at, m.moveHolds, moveHoldEnded) if err != nil { slog.Error("end move hold", "login", login, "err", err) } @@ -702,21 +704,24 @@ const moveHold = 10 * time.Second const moveHoldEnded = "The move hold is over: the human moved the right pane 10 seconds ago and hasn't moved it since, and a show of yours was refused in that time, so show works again under its other rules." -func (m *Manager) endMoveHold(ctx context.Context, login string, at time.Time) error { +type showHold struct { + at time.Time + refused bool +} + +func (m *Manager) endShowHold(ctx context.Context, login string, at time.Time, holds map[string]showHold, text string) error { m.mu.Lock() - current, ok := m.humanMoved[login] - if !ok || !current.Equal(at) { + hold := holds[login] + if !hold.at.Equal(at) { m.mu.Unlock() return nil } - delete(m.humanMoved, login) - refused := m.moveRefused[login] - delete(m.moveRefused, login) + delete(holds, login) m.mu.Unlock() - if !refused { + if !hold.refused { return nil } - return m.addLeadInput(ctx, store.LeadInput{Owner: login, Kind: store.LeadSignal, Actor: "byre", Text: moveHoldEnded}) + return m.addLeadInput(ctx, store.LeadInput{Owner: login, Kind: store.LeadSignal, Actor: "byre", Text: text}) } const startHold = 10 * time.Second @@ -726,38 +731,20 @@ const startHoldEnded = "The start hold is over: the human started a TODO item 10 func (m *Manager) setStartedTodo(login string, started bool) { m.mu.Lock() defer m.mu.Unlock() - delete(m.startRefused, login) if !started { - delete(m.startedTodo, login) + delete(m.startHolds, login) return } at := time.Now() - m.startedTodo[login] = at + m.startHolds[login] = showHold{at: at} time.AfterFunc(startHold, func() { - err := m.endStartHold(context.Background(), login, at) + err := m.endShowHold(context.Background(), login, at, m.startHolds, startHoldEnded) if err != nil { slog.Error("end start hold", "login", login, "err", err) } }) } -func (m *Manager) endStartHold(ctx context.Context, login string, at time.Time) error { - m.mu.Lock() - current, ok := m.startedTodo[login] - if !ok || !current.Equal(at) { - m.mu.Unlock() - return nil - } - delete(m.startedTodo, login) - refused := m.startRefused[login] - delete(m.startRefused, login) - m.mu.Unlock() - if !refused { - return nil - } - return m.addLeadInput(ctx, store.LeadInput{Owner: login, Kind: store.LeadSignal, Actor: "byre", Text: startHoldEnded}) -} - func (m *Manager) modelOr(model string, l *live) string { if model != "" { return model diff --git a/internal/agents/manager.go b/internal/agents/manager.go index 73685c1..277d22a 100644 --- a/internal/agents/manager.go +++ b/internal/agents/manager.go @@ -58,10 +58,8 @@ type Manager struct { paneFocus map[string]api.PaneFocus paneReported map[string]time.Time paneMoved map[string]time.Time - humanMoved map[string]time.Time - moveRefused map[string]bool - startedTodo map[string]time.Time - startRefused map[string]bool + moveHolds map[string]showHold + startHolds map[string]showHold handoffModel map[string]string mergeTurns map[string]mergeTurn @@ -163,10 +161,8 @@ func New(st *store.Store, worktreeRoot, leadRoot, handsRoot, codexHome, antigrav paneFocus: map[string]api.PaneFocus{}, paneReported: map[string]time.Time{}, paneMoved: map[string]time.Time{}, - humanMoved: map[string]time.Time{}, - moveRefused: map[string]bool{}, - startedTodo: map[string]time.Time{}, - startRefused: map[string]bool{}, + moveHolds: map[string]showHold{}, + startHolds: map[string]showHold{}, handoffModel: map[string]string{}, mergeTurns: map[string]mergeTurn{}, signals: make(chan []api.Event, 1024),