diff --git a/internal/agents/lead.go b/internal/agents/lead.go index 96c1845..7d6cb7d 100644 --- a/internal/agents/lead.go +++ b/internal/agents/lead.go @@ -267,7 +267,7 @@ func (m *Manager) leadStateText(ctx context.Context, owner string) (string, erro pane = fmt.Sprintf("Your right pane shows project %s (%s) with no task: its dashboard.", project.Name, project.Id) } m.mu.Lock() - focused := m.paneFocus[owner].Focused + focused := m.paneReports[owner].Focused m.mu.Unlock() if focused { pane += " The human is working in it." diff --git a/internal/agents/leadtools.go b/internal/agents/leadtools.go index 2b2f63e..8d0240a 100644 --- a/internal/agents/leadtools.go +++ b/internal/agents/leadtools.go @@ -519,7 +519,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool { return "Already shown: the right pane shows that now, so nothing changed.", nil } m.mu.Lock() - working := m.paneFocus[user.Login].Focused || m.paneFocus[user.Login].Drafting + working := m.paneReports[user.Login].Focused || m.paneReports[user.Login].Drafting move := m.moveHolds[user.Login] start := m.startHolds[user.Login] since := time.Since(move.at) @@ -624,7 +624,7 @@ func (m *Manager) SetFocus(ctx context.Context, login string, f api.Focus, actor func (m *Manager) endWatchHold(ctx context.Context, login string, at time.Time) error { m.mu.Lock() moved := m.paneMoved[login] - focused := m.paneFocus[login].Focused + focused := m.paneReports[login].Focused m.mu.Unlock() if !moved.Equal(at) || !focused { return nil @@ -713,8 +713,7 @@ func (m *Manager) paneWaiting(ctx context.Context, login string, f api.Focus) (b return false, nil } m.mu.Lock() - drafting := m.paneFocus[login].Drafting - reported := m.paneReported[login] + report := m.paneReports[login] moved := m.paneMoved[login] m.mu.Unlock() turn, running, err := m.store.RunningTurn(ctx, *f.TaskId) @@ -723,16 +722,20 @@ func (m *Manager) paneWaiting(ctx context.Context, login string, f api.Focus) (b } if turn.Actor == login && turn.At.After(moved) { // The report of the composer emptying on send can arrive after the turn starts. - return !drafting || reported.Before(turn.At), nil + return !report.Drafting || report.at.Before(turn.At), nil } - return !drafting && time.Since(moved) >= watchHold, nil + return !report.Drafting && time.Since(moved) >= watchHold, nil +} + +type paneReport struct { + api.PaneFocus + at time.Time } func (m *Manager) SetPaneFocus(login string, p api.PaneFocus) { m.mu.Lock() defer m.mu.Unlock() - m.paneFocus[login] = p - m.paneReported[login] = time.Now() + m.paneReports[login] = paneReport{PaneFocus: p, at: time.Now()} } const moveHold = 10 * time.Second diff --git a/internal/agents/manager.go b/internal/agents/manager.go index 5e90f36..dce4cf8 100644 --- a/internal/agents/manager.go +++ b/internal/agents/manager.go @@ -56,8 +56,7 @@ type Manager struct { closing bool rateLimits map[api.AgentSessionVendor]api.Usage usageCommands map[api.AgentSessionVendor]string - paneFocus map[string]api.PaneFocus - paneReported map[string]time.Time + paneReports map[string]paneReport paneMoved map[string]time.Time moveHolds map[string]showHold startHolds map[string]showHold @@ -162,8 +161,7 @@ func New(st *store.Store, worktreeRoot, leadRoot, handsRoot, codexHome, antigrav rateLimits: map[api.AgentSessionVendor]api.Usage{}, usageCommands: map[api.AgentSessionVendor]string{}, usageMu: map[api.AgentSessionVendor]*sync.Mutex{api.Claude: {}, api.Codex: {}, api.Antigravity: {}}, - paneFocus: map[string]api.PaneFocus{}, - paneReported: map[string]time.Time{}, + paneReports: map[string]paneReport{}, paneMoved: map[string]time.Time{}, moveHolds: map[string]showHold{}, startHolds: map[string]showHold{},