From c24e3c18e0177e2e059f622a63e87249c52db2d5 Mon Sep 17 00:00:00 2001 From: Kujtim Hoxha Date: Thu, 17 Apr 2025 13:45:26 +0200 Subject: small improvements --- internal/tui/components/core/status.go | 56 +++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'internal/tui/components/core') diff --git a/internal/tui/components/core/status.go b/internal/tui/components/core/status.go index 411cac1c5..e76ecde84 100644 --- a/internal/tui/components/core/status.go +++ b/internal/tui/components/core/status.go @@ -11,6 +11,9 @@ import ( "github.com/kujtimiihoxha/opencode/internal/llm/models" "github.com/kujtimiihoxha/opencode/internal/lsp" "github.com/kujtimiihoxha/opencode/internal/lsp/protocol" + "github.com/kujtimiihoxha/opencode/internal/pubsub" + "github.com/kujtimiihoxha/opencode/internal/session" + "github.com/kujtimiihoxha/opencode/internal/tui/components/chat" "github.com/kujtimiihoxha/opencode/internal/tui/styles" "github.com/kujtimiihoxha/opencode/internal/tui/util" ) @@ -20,6 +23,7 @@ type statusCmp struct { width int messageTTL time.Duration lspClients map[string]*lsp.Client + session session.Session } // clearMessageCmd is a command that clears status messages after a timeout @@ -38,6 +42,16 @@ func (m statusCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.WindowSizeMsg: m.width = msg.Width return m, nil + case chat.SessionSelectedMsg: + m.session = msg + case chat.SessionClearedMsg: + m.session = session.Session{} + case pubsub.Event[session.Session]: + if msg.Type == pubsub.UpdatedEvent { + if m.session.ID == msg.Payload.ID { + m.session = msg.Payload + } + } case util.InfoMsg: m.info = msg ttl := msg.TTL @@ -53,8 +67,43 @@ func (m statusCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var helpWidget = styles.Padded.Background(styles.ForgroundMid).Foreground(styles.BackgroundDarker).Bold(true).Render("ctrl+? help") +func formatTokensAndCost(tokens int64, cost float64) string { + // Format tokens in human-readable format (e.g., 110K, 1.2M) + var formattedTokens string + switch { + case tokens >= 1_000_000: + formattedTokens = fmt.Sprintf("%.1fM", float64(tokens)/1_000_000) + case tokens >= 1_000: + formattedTokens = fmt.Sprintf("%.1fK", float64(tokens)/1_000) + default: + formattedTokens = fmt.Sprintf("%d", tokens) + } + + // Remove .0 suffix if present + if strings.HasSuffix(formattedTokens, ".0K") { + formattedTokens = strings.Replace(formattedTokens, ".0K", "K", 1) + } + if strings.HasSuffix(formattedTokens, ".0M") { + formattedTokens = strings.Replace(formattedTokens, ".0M", "M", 1) + } + + // Format cost with $ symbol and 2 decimal places + formattedCost := fmt.Sprintf("$%.2f", cost) + + return fmt.Sprintf("Tokens: %s, Cost: %s", formattedTokens, formattedCost) +} + func (m statusCmp) View() string { status := helpWidget + if m.session.ID != "" { + tokens := formatTokensAndCost(m.session.PromptTokens+m.session.CompletionTokens, m.session.Cost) + tokensStyle := styles.Padded. + Background(styles.Forground). + Foreground(styles.BackgroundDim). + Render(tokens) + status += tokensStyle + } + diagnostics := styles.Padded.Background(styles.BackgroundDarker).Render(m.projectDiagnostics()) if m.info.Msg != "" { infoStyle := styles.Padded. @@ -82,6 +131,7 @@ func (m statusCmp) View() string { Width(m.availableFooterMsgWidth(diagnostics)). Render("") } + status += diagnostics status += m.model() return status @@ -136,7 +186,11 @@ func (m *statusCmp) projectDiagnostics() string { } func (m statusCmp) availableFooterMsgWidth(diagnostics string) int { - return max(0, m.width-lipgloss.Width(helpWidget)-lipgloss.Width(m.model())-lipgloss.Width(diagnostics)) + tokens := "" + if m.session.ID != "" { + tokens = formatTokensAndCost(m.session.PromptTokens+m.session.CompletionTokens, m.session.Cost) + } + return max(0, m.width-lipgloss.Width(helpWidget)-lipgloss.Width(m.model())-lipgloss.Width(diagnostics)-lipgloss.Width(tokens)) } func (m statusCmp) model() string { -- cgit v1.2.3