Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions cmd/roborev/tui/queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2200,12 +2200,22 @@ func TestParseColumnOrderAppendsMissing(t *testing.T) {
assert.True(t, slices.Equal(got[:len(wantPrefix)], wantPrefix))

pfCount := 0
requestedModelCount := 0
requestedProviderCount := 0
for _, c := range got {
if c == colPF {
pfCount++
}
if c == colRequestedModel {
requestedModelCount++
}
if c == colRequestedProvider {
requestedProviderCount++
}
}
assert.Equal(t, 1, pfCount)
assert.Equal(t, 1, requestedModelCount)
assert.Equal(t, 1, requestedProviderCount)
}

func TestDefaultColumnOrderDetection(t *testing.T) {
Expand All @@ -2221,3 +2231,10 @@ func TestDefaultColumnOrderDetection(t *testing.T) {

assert.False(t, slices.Equal(customOrder, toggleableColumns))
}

func TestDefaultHiddenColumnsIncludeRequestedFields(t *testing.T) {
hidden := parseHiddenColumns(nil)
assert.True(t, hidden[colSessionID])
assert.True(t, hidden[colRequestedModel])
assert.True(t, hidden[colRequestedProvider])
}
107 changes: 60 additions & 47 deletions cmd/roborev/tui/render_queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,21 @@ func (m model) getVisibleSelectedIdx() int {

// Queue table column indices.
const (
colSel = iota // "> " selection indicator
colJobID // Job ID
colRef // Git ref (short SHA or range)
colBranch // Branch name
colRepo // Repository display name
colAgent // Agent name
colQueued // Enqueue timestamp
colElapsed // Elapsed time
colStatus // Job status
colPF // Pass/Fail verdict
colHandled // Done status
colSessionID // Session ID
colCount // total number of columns
colSel = iota // "> " selection indicator
colJobID // Job ID
colRef // Git ref (short SHA or range)
colBranch // Branch name
colRepo // Repository display name
colAgent // Agent name
colQueued // Enqueue timestamp
colElapsed // Elapsed time
colStatus // Job status
colPF // Pass/Fail verdict
colHandled // Done status
colSessionID // Session ID
colRequestedModel // Explicitly requested model
colRequestedProvider // Explicitly requested provider
colCount // total number of columns
)

func (m model) renderQueueView() string {
Expand Down Expand Up @@ -309,15 +311,17 @@ func (m model) renderQueueView() string {

// Fixed-width columns: exact sizes (content + padding, not counting inter-column spacing)
fixedWidth := map[int]int{
colSel: 2,
colJobID: idWidth,
colStatus: max(contentWidth[colStatus], 6), // "Status" header = 6, auto-sizes to content
colQueued: 12,
colElapsed: 8,
colPF: 3, // "P/F" header = 3
colHandled: max(contentWidth[colHandled], 6), // "Closed" header = 6
colAgent: min(max(contentWidth[colAgent], 5), 12), // "Agent" header = 5, cap at 12
colSessionID: min(max(contentWidth[colSessionID], 7), 12), // "Session" header = 7, cap at 12
colSel: 2,
colJobID: idWidth,
colStatus: max(contentWidth[colStatus], 6), // "Status" header = 6, auto-sizes to content
colQueued: 12,
colElapsed: 8,
colPF: 3, // "P/F" header = 3
colHandled: max(contentWidth[colHandled], 6), // "Closed" header = 6
colAgent: min(max(contentWidth[colAgent], 5), 12), // "Agent" header = 5, cap at 12
colSessionID: min(max(contentWidth[colSessionID], 7), 12), // "Session" header = 7, cap at 12
colRequestedModel: min(max(contentWidth[colRequestedModel], 15), 24), // "Req Model" header = 9
colRequestedProvider: min(max(contentWidth[colRequestedProvider], 18), 24), // "Req Provider" header = 12
}

// Flexible columns absorb excess space
Expand Down Expand Up @@ -593,8 +597,8 @@ func (m model) renderQueueView() string {
}

// jobCells returns plain text cell values for a job row.
// Order: ref, branch, repo, agent, queued, elapsed, status, pf, handled
// (colRef through colHandled, 9 values).
// Order: ref, branch, repo, agent, queued, elapsed, status, pf, handled,
// session, requested model, requested provider.
func (m model) jobCells(job storage.ReviewJob) []string {
ref := shortJobRef(job)
if !config.IsDefaultReviewType(job.ReviewType) {
Expand Down Expand Up @@ -645,7 +649,10 @@ func (m model) jobCells(job storage.ReviewJob) []string {
sessionID = string(runes[:12])
}

return []string{ref, branch, repo, agentName, enqueued, elapsed, status, verdict, handled, sessionID}
requestedModel := stripControlChars(job.RequestedModel)
requestedProvider := stripControlChars(job.RequestedProvider)

return []string{ref, branch, repo, agentName, enqueued, elapsed, status, verdict, handled, sessionID, requestedModel, requestedProvider}
}

// statusLabel returns a capitalized display label for the job status.
Expand Down Expand Up @@ -770,34 +777,38 @@ func migrateColumnConfig(cfg *config.Config) bool {

// toggleableColumns is the ordered list of columns the user can show/hide.
// colSel and colJobID are always visible and not included here.
var toggleableColumns = []int{colRef, colBranch, colRepo, colAgent, colQueued, colElapsed, colStatus, colPF, colHandled, colSessionID}
var toggleableColumns = []int{colRef, colBranch, colRepo, colAgent, colQueued, colElapsed, colStatus, colPF, colHandled, colSessionID, colRequestedModel, colRequestedProvider}

// columnNames maps column constants to display names.
var columnNames = map[int]string{
colRef: "Ref",
colBranch: "Branch",
colRepo: "Repo",
colAgent: "Agent",
colStatus: "Status",
colQueued: "Queued",
colElapsed: "Elapsed",
colPF: "P/F",
colHandled: "Closed",
colSessionID: "Session",
colRef: "Ref",
colBranch: "Branch",
colRepo: "Repo",
colAgent: "Agent",
colStatus: "Status",
colQueued: "Queued",
colElapsed: "Elapsed",
colPF: "P/F",
colHandled: "Closed",
colSessionID: "Session",
colRequestedModel: "Req Model",
colRequestedProvider: "Req Provider",
}

// columnConfigNames maps column constants to config file names (lowercase).
var columnConfigNames = map[int]string{
colRef: "ref",
colBranch: "branch",
colRepo: "repo",
colAgent: "agent",
colStatus: "status",
colQueued: "queued",
colElapsed: "elapsed",
colPF: "pf",
colHandled: "closed",
colSessionID: "session_id",
colRef: "ref",
colBranch: "branch",
colRepo: "repo",
colAgent: "agent",
colStatus: "status",
colQueued: "queued",
colElapsed: "elapsed",
colPF: "pf",
colHandled: "closed",
colSessionID: "session_id",
colRequestedModel: "requested_model",
colRequestedProvider: "requested_provider",
}

// drainFlexOverflow reduces flex column widths to absorb overflow,
Expand Down Expand Up @@ -838,7 +849,9 @@ func columnDisplayName(col int) string {
// defaultHiddenColumns lists columns that are hidden by default.
// Users can enable them via the column options modal.
var defaultHiddenColumns = map[int]bool{
colSessionID: true,
colSessionID: true,
colRequestedModel: true,
colRequestedProvider: true,
}

// parseHiddenColumns converts config hidden_columns strings to column ID set.
Expand Down
2 changes: 1 addition & 1 deletion cmd/roborev/tui/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ func newModel(ep daemon.DaemonEndpoint, opts ...option) model {
tabWidth := 2
columnBorders := false
tasksEnabled := false
hiddenCols := map[int]bool{}
hiddenCols := parseHiddenColumns(nil)
colOrder := parseColumnOrder(nil)
taskColOrder := parseTaskColumnOrder(nil)
var cwdRepoRoot, cwdBranch string
Expand Down
2 changes: 1 addition & 1 deletion cmd/roborev/tui/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const (
)

// columnOption represents an item in the column options modal.
// id is a column constant (colRef..colHandled) or a sentinel option ID.
// id is a queue column constant or a sentinel option ID.
type columnOption struct {
id int // column constant or sentinel option ID
name string // display label
Expand Down
Loading
Loading