TUI: Closed column, legacy 30m stale window, filtered-view fix, header shown-count, toggle tests

This commit is contained in:
2026-08-04 11:13:36 +10:00
parent 19b39de473
commit a0d25aa108
3 changed files with 141 additions and 52 deletions

66
main.go
View File

@@ -67,7 +67,8 @@ var sortNames = map[int]string{
type model struct {
table table.Model
help help.Model
agents []AgentState // filtered + sorted view
agents []AgentState // all agents from the last poll (unfiltered)
view []AgentState // filtered + sorted view backing the table
config Config
hideClosed bool
hideSubagents bool
@@ -86,10 +87,10 @@ func initialModel(cfg Config) model {
{Title: "Session", Width: 16},
{Title: "Folder", Width: 16},
{Title: "Status", Width: 10},
{Title: "Model", Width: 14},
{Title: "Started", Width: 10},
{Title: "Closed", Width: 10},
{Title: "Tools", Width: 5},
{Title: "Task", Width: 24},
{Title: "Task", Width: 20},
}
t := table.New(
@@ -229,7 +230,7 @@ func (m model) View() string {
live++
}
}
summary := fmt.Sprintf("%d agent(s) · %d live · %d closed", len(m.agents), live, closed)
summary := fmt.Sprintf("%d shown of %d agents · %d live · %d closed", len(m.view), len(m.agents), live, closed)
if m.hideClosed {
summary += " │ closed hidden"
}
@@ -273,14 +274,14 @@ func (m model) View() string {
}
func (m model) detailView() string {
if len(m.agents) == 0 {
if len(m.view) == 0 {
return ""
}
row := m.table.Cursor()
if row < 0 || row >= len(m.agents) {
if row < 0 || row >= len(m.view) {
return ""
}
a := m.agents[row]
a := m.view[row]
stale := m.staleAfter()
term := a.TerminalType
@@ -373,6 +374,7 @@ func (m *model) updateTable() {
}
view = append(view, a)
}
m.view = view
// Sort
sortAgents(view, m.sortMode, m.staleAfter())
@@ -385,16 +387,24 @@ func (m *model) updateTable() {
session = "◇ " + session
}
task := strings.ReplaceAll(a.CurrentTask, "\n", " ")
if len(task) > 24 {
task = task[:22] + ".."
if len(task) > 20 {
task = task[:18] + ".."
}
var closedTime string
if a.IsClosed(m.staleAfter()) {
if a.ClosedAt != nil && *a.ClosedAt != "" {
closedTime = fmtTime(a.ClosedAt)
} else {
closedTime = fmtTime(a.LastSeenAt) // approx: last seen
}
}
rows = append(rows, table.Row{
termSymbol(a.TerminalType, a.ConnectionType),
trunc(session, 16),
trunc(a.Folder(), 16),
a.StatusStr(m.staleAfter()),
a.ShortModel(),
fmtTime(a.SessionStartedAt),
closedTime,
fmt.Sprintf("%d", a.ToolCalls),
task,
})
@@ -507,14 +517,14 @@ type errMsg struct{ err error }
// `zellij action switch-session` when the dashboard itself runs inside zellij
// - direct → no attach target; show an error
func attachToAgent(m model) tea.Cmd {
if len(m.agents) == 0 {
if len(m.view) == 0 {
return nil
}
row := m.table.Cursor()
if row < 0 || row >= len(m.agents) {
if row < 0 || row >= len(m.view) {
return nil
}
a := m.agents[row]
a := m.view[row]
term := a.TerminalType
if term == "" {
@@ -573,14 +583,14 @@ func attachToAgent(m model) tea.Cmd {
// openHunk reviews the selected agent's changes with Hunk, in the folder
// the agent was actually running in.
func openHunk(m model) tea.Cmd {
if len(m.agents) == 0 {
if len(m.view) == 0 {
return nil
}
row := m.table.Cursor()
if row < 0 || row >= len(m.agents) {
if row < 0 || row >= len(m.view) {
return nil
}
a := m.agents[row]
a := m.view[row]
if a.Cwd == "" {
m.err = fmt.Errorf("no folder recorded for %s", a.Session)
@@ -628,10 +638,10 @@ func openTuxedo(m model) tea.Cmd {
var todoPath string
var agent AgentState
haveAgent := false
if len(m.agents) > 0 {
if len(m.view) > 0 {
row := m.table.Cursor()
if row >= 0 && row < len(m.agents) {
agent = m.agents[row]
if row >= 0 && row < len(m.view) {
agent = m.view[row]
haveAgent = true
if agent.Cwd != "" {
todoPath = agent.Cwd + "/.pi/dashboard/tasks/todo.txt"
@@ -732,22 +742,32 @@ func printAgentList(agents []AgentState) {
fmt.Println("No agents found in ~/.pi/agent/dashboard/")
return
}
fmt.Printf("%-6s %-18s %-16s %-10s %-10s %s\n", "Type", "Session", "Folder", "Status", "Started", "Task")
fmt.Println(strings.Repeat("-", 100))
stale := 45 * time.Second
fmt.Printf("%-6s %-18s %-16s %-10s %-10s %-10s %s\n", "Type", "Session", "Folder", "Status", "Started", "Closed", "Task")
fmt.Println(strings.Repeat("-", 110))
for _, a := range agents {
task := strings.ReplaceAll(a.CurrentTask, "\n", " ")
if len(task) > 35 {
task = task[:33] + ".."
}
fmt.Printf("%-6s %-18s %-16s %-10s %-10s %s\n",
var closedTime string
if a.IsClosed(stale) {
if a.ClosedAt != nil && *a.ClosedAt != "" {
closedTime = fmtTime(a.ClosedAt)
} else {
closedTime = fmtTime(a.LastSeenAt)
}
}
fmt.Printf("%-6s %-18s %-16s %-10s %-10s %-10s %s\n",
termSymbol(a.TerminalType, a.ConnectionType),
trunc(a.Session, 18),
trunc(a.Folder(), 16),
statusStr(a),
fmtTime(a.SessionStartedAt),
closedTime,
task)
}
fmt.Println(strings.Repeat("-", 100))
fmt.Println(strings.Repeat("-", 110))
fmt.Println("Type: Ⓣ tmux · Ⓩ zellij · ⓉⓏ both · · direct")
}