feat(ui): add hypercredit readout to small top header

Christian Rocha created

Change summary

internal/ui/common/elements.go   | 6 +++---
internal/ui/model/header.go      | 8 ++++++++
internal/ui/model/ui.go          | 1 +
internal/ui/styles/quickstyle.go | 1 +
internal/ui/styles/styles.go     | 1 +
5 files changed, 14 insertions(+), 3 deletions(-)

Detailed changes

internal/ui/common/elements.go πŸ”—

@@ -81,7 +81,7 @@ func ModelInfo(t *styles.Styles, modelName, providerName, reasoningInfo string,
 	if providerName == hyper.DisplayName && hyperCredits != nil {
 		hcInfo := t.ModelInfo.HypercreditIcon.Render(styles.HypercreditIcon)
 		hcInfo += " "
-		hcInfo += t.ModelInfo.HypercreditText.Render(fmt.Sprintf("%s Hypercredits", formatCredits(*hyperCredits)))
+		hcInfo += t.ModelInfo.HypercreditText.Render(fmt.Sprintf("%s Hypercredits", FormatCredits(*hyperCredits)))
 		parts = append(parts, "", hcInfo)
 	}
 
@@ -124,8 +124,8 @@ func formatTokensAndCost(t *styles.Styles, tokens, contextWindow int64, cost flo
 	return fmt.Sprintf("%s %s", formattedTokens, formattedCost)
 }
 
-// formatCredits formats an integer with comma separators for thousands.
-func formatCredits(n int) string {
+// FormatCredits formats an integer with comma separators for thousands.
+func FormatCredits(n int) string {
 	s := strconv.FormatInt(int64(n), 10)
 	if n < 1000 {
 		return s

internal/ui/model/header.go πŸ”—

@@ -69,6 +69,7 @@ func (h *header) drawHeader(
 	compact bool,
 	detailsOpen bool,
 	width int,
+	hyperCredits *int,
 ) {
 	t := h.com.Styles
 	if width != h.width || compact != h.compact {
@@ -101,6 +102,7 @@ func (h *header) drawHeader(
 		lspErrorCount,
 		detailsOpen,
 		availDetailWidth,
+		hyperCredits,
 	)
 
 	remainingWidth := width -
@@ -131,6 +133,7 @@ func renderHeaderDetails(
 	lspErrorCount int,
 	detailsOpen bool,
 	availWidth int,
+	hyperCredits *int,
 ) string {
 	t := com.Styles
 
@@ -148,6 +151,11 @@ func renderHeaderDetails(
 		parts = append(parts, formattedPercentage)
 	}
 
+	if com.IsHyper() && hyperCredits != nil {
+		hc := t.Header.Hypercredit.Render(styles.HypercreditIcon) + " " + t.Header.Percentage.Render(common.FormatCredits(*hyperCredits))
+		parts = append(parts, hc)
+	}
+
 	const keystroke = "ctrl+d"
 	if detailsOpen {
 		parts = append(parts, t.Header.Keystroke.Render(keystroke)+t.Header.KeystrokeTip.Render(" close"))

internal/ui/model/ui.go πŸ”—

@@ -2109,6 +2109,7 @@ func (m *UI) drawHeader(scr uv.Screen, area uv.Rectangle) {
 		m.isCompact,
 		m.detailsOpen,
 		area.Dx(),
+		m.hyperCredits,
 	)
 }
 

internal/ui/styles/quickstyle.go πŸ”—

@@ -577,6 +577,7 @@ func quickStyle(o quickStyleOpts) Styles {
 	s.Header.Charm = base.Foreground(o.secondary)
 	s.Header.Diagonals = base.Foreground(o.primary)
 	s.Header.Percentage = muted
+	s.Header.Hypercredit = base.Foreground(charmtone.Dolly)
 	s.Header.Keystroke = muted
 	s.Header.KeystrokeTip = subtle
 	s.Header.WorkingDir = muted

internal/ui/styles/styles.go πŸ”—

@@ -64,6 +64,7 @@ type Styles struct {
 		Charm             lipgloss.Style // Style for "Charmβ„’" label
 		Diagonals         lipgloss.Style // Style for diagonal separators (β•±)
 		Percentage        lipgloss.Style // Style for context percentage
+		Hypercredit       lipgloss.Style // Style for Hypercredit count (β—† N)
 		Keystroke         lipgloss.Style // Style for keystroke hints (e.g., "ctrl+d")
 		KeystrokeTip      lipgloss.Style // Style for keystroke action text (e.g., "open", "close")
 		WorkingDir        lipgloss.Style // Style for current working directory