Let the lead reorder tabs on what the pane already shows

This commit is contained in:
Ian Gulliver
2026-10-15 10:45:08 -07:00
parent 535f5579f9
commit f360d14655
3 changed files with 45 additions and 6 deletions
+17
View File
@@ -2,6 +2,7 @@ package agents_test
import (
"fmt"
"slices"
"strings"
"testing"
"time"
@@ -89,6 +90,22 @@ func TestLeadSignalsAndShow(t *testing.T) {
t.Fatalf("focus moved while the pane was focused: %+v", f)
}
_, err = m.MessageLead(e.ctx, e.user, "Call the show tool with task_id "+e.task.Id+", tabs [\"inbox\", \"changes\"] and tab \"inbox\". Then say done.", "", nil)
if err != nil {
t.Fatalf("message lead: %v", err)
}
e.waitFor("show of what is already shown", func(ev api.Event) bool {
return ev.Kind == "agent.tool_result" && ev.Owner != nil && strings.Contains(fmt.Sprint(ev.Payload), "Already shown")
})
e.waitFor("lead idle after already-shown show", leadIdle)
f, err = e.store.GetFocus(e.ctx, login)
if err != nil {
t.Fatalf("get focus: %v", err)
}
if f.Tab != api.TabInbox || !slices.Equal(f.Tabs, []api.TaskTab{api.TabInbox, api.TabChanges}) {
t.Fatalf("tabs not reordered on the shown tab: %+v", f)
}
err = e.store.WithdrawItem(e.ctx, created[len(created)-1].Payload["id"].(string))
if err != nil {
t.Fatalf("withdraw report: %v", err)
+27 -5
View File
@@ -295,7 +295,8 @@ func (m *Manager) leadTools(l *live) []mcp.Tool {
"Point the human's right pane at a task, or at a project with no task: tabs are the tabs to put first, in order (the rest follow), and tab is the one to select. "+
"Tabs: transcript, changes, files, inbox (the task's open items), project (the project's dashboard: its active tasks and its TODO.md items); with only project_id, only project shows anything. "+
"Omit both task_id and project_id to clear the pane. "+
"Refused while the human is working in the right pane, unless what it shows is finished (a merged or discarded task, or an inbox tab with nothing left).",
"If the pane already shows that task (or project) on that tab, only the tab order changes and you are told so, even while the human is working in the pane. "+
"Otherwise refused while the human is working in the right pane, unless what it shows is finished (a merged or discarded task, or an inbox tab with nothing left).",
`{"type": "object", "properties": {
"task_id": {"type": "string"},
"project_id": {"type": "string", "description": "Ignored when task_id is given."},
@@ -308,14 +309,24 @@ func (m *Manager) leadTools(l *live) []mcp.Tool {
if err != nil {
return "", err
}
current, err := m.store.GetFocus(ctx, user.Login)
if err != nil {
return "", err
}
if sameView(current, f) {
if slices.Equal(current.Tabs, f.Tabs) {
return "Already shown: the right pane shows that now, so nothing changed.", nil
}
err = m.SetFocus(ctx, user.Login, f, leadActor(user.Login))
if err != nil {
return "", err
}
return "Already shown on that tab; the tab order was updated.", nil
}
m.mu.Lock()
focused := m.paneFocused[user.Login]
m.mu.Unlock()
if focused {
current, err := m.store.GetFocus(ctx, user.Login)
if err != nil {
return "", err
}
finished, err := m.paneFinished(ctx, current)
if err != nil {
return "", err
@@ -370,6 +381,17 @@ func (m *Manager) SetFocus(ctx context.Context, login string, f api.Focus, actor
return m.store.SetFocus(ctx, login, f, actor)
}
func sameView(a, b api.Focus) bool {
if a.Tab != b.Tab {
return false
}
at, bt := deref(a.TaskId), deref(b.TaskId)
if at != "" || bt != "" {
return at == bt
}
return deref(a.ProjectId) == deref(b.ProjectId)
}
const inboxEmptied = "has nothing left in its inbox"
func (m *Manager) paneFinished(ctx context.Context, f api.Focus) (string, error) {