feat(tui): full event history, approval-decision events, status bar
- Events were hard-capped to the last 7 per session in addEvent, so the e-inspector and EVENTS panel could never show more. Raise to 1000 (effectively all, bounded); the EVENTS panel now shows the latest that fit (tail), and the inspector scrolls a window around the selection with a position indicator. - The TUI had no approval.resolved handling at all — the decision frame was ignored and pending only cleared on session.resumed. Add the constant + case: clear the gate and record an ApprovalResolved event (APPROVED/REJECTED/AUTO_APPROVED + reason) into the stream. - Status bar now shows the current stage and session status alongside the name. Relabel the cryptic "N bg" badge to "N elsewhere".
This commit is contained in:
@@ -69,7 +69,10 @@ func (m Model) renderStatus() string {
|
||||
if s := m.session(m.selectedID); s != nil && m.displayState() != StateIdle {
|
||||
parts = append(parts, span(s.Name, t.P.FgStrong))
|
||||
if s.CurrentStage != "" {
|
||||
parts = append(parts, span(s.CurrentStage, t.P.Accent2))
|
||||
parts = append(parts, span("⟐ "+s.CurrentStage, t.P.Accent2))
|
||||
}
|
||||
if s.Status != "" {
|
||||
parts = append(parts, lipgloss.NewStyle().Foreground(statusColor(t, s.Status)).Background(bg).Render(statusLabel(s.Status)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +95,7 @@ func (m Model) renderStatus() string {
|
||||
right = append(right, lipgloss.NewStyle().Foreground(t.P.Accent).Background(bg).Render(m.spinner())+span(" active", t.P.Accent2))
|
||||
}
|
||||
if m.bgUpdates > 0 {
|
||||
right = append(right, span(itoa(m.bgUpdates)+" bg", t.P.Warn))
|
||||
right = append(right, span(itoa(m.bgUpdates)+" elsewhere", t.P.Warn))
|
||||
}
|
||||
if len(right) == 0 {
|
||||
return m.fill(left, m.width, bg)
|
||||
@@ -185,7 +188,7 @@ func (m Model) renderMain(h int) string {
|
||||
leftBody = m.routerRows(leftW-4, h-2)
|
||||
leftActive = true
|
||||
rightTitle = "events"
|
||||
rightBody = m.eventRows(rightW - 4)
|
||||
rightBody = m.eventRows(rightW-4, h)
|
||||
}
|
||||
|
||||
left := m.theme.box(leftTitle, leftBody, leftW, h, leftActive)
|
||||
@@ -356,7 +359,7 @@ func (m Model) routerRows(w, h int) []string {
|
||||
return rows
|
||||
}
|
||||
|
||||
func (m Model) eventRows(w int) []string {
|
||||
func (m Model) eventRows(w, h int) []string {
|
||||
t := m.theme
|
||||
header := lipgloss.NewStyle().Foreground(t.P.Accent).Background(t.P.Bg).Bold(true).Render("event stream") +
|
||||
t.span(" ", t.P.Bg)
|
||||
@@ -366,21 +369,24 @@ func (m Model) eventRows(w int) []string {
|
||||
header += t.span("○ idle", t.P.Faint)
|
||||
}
|
||||
|
||||
rows := []string{header, ""}
|
||||
s := m.session(m.selectedID)
|
||||
if s == nil || len(s.Events) == 0 {
|
||||
rows = append(rows, t.span("no events yet", t.P.Faint))
|
||||
return rows
|
||||
return []string{header, "", t.span("no events yet", t.P.Faint)}
|
||||
}
|
||||
evRows := make([]string, 0, len(s.Events))
|
||||
for _, e := range s.Events {
|
||||
cat := inferCategory(e.Type)
|
||||
catCell := lipgloss.NewStyle().Foreground(t.categoryColor(cat)).Background(t.P.BgPanel).
|
||||
Render(" " + padRaw(cat, 9) + " ")
|
||||
rows = append(rows,
|
||||
evRows = append(evRows,
|
||||
t.span(e.Time+" ", t.P.Faint)+catCell+" "+
|
||||
t.span(padRaw(e.Type, 18), t.P.Fg)+t.span(e.Detail, t.P.Dim))
|
||||
}
|
||||
return rows
|
||||
// Show the latest events that fit under the 2-line header (box inner = h-2).
|
||||
if avail := h - 4; avail >= 1 && len(evRows) > avail {
|
||||
evRows = evRows[len(evRows)-avail:]
|
||||
}
|
||||
return append([]string{header, ""}, evRows...)
|
||||
}
|
||||
|
||||
// --- width helpers ---
|
||||
|
||||
Reference in New Issue
Block a user