diff options
Diffstat (limited to 'internal/tmux/status.go')
| -rw-r--r-- | internal/tmux/status.go | 88 |
1 files changed, 75 insertions, 13 deletions
diff --git a/internal/tmux/status.go b/internal/tmux/status.go index 4e1f9e4..1d2a8ee 100644 --- a/internal/tmux/status.go +++ b/internal/tmux/status.go @@ -1,28 +1,90 @@ package tmux import ( - "os" - "os/exec" - "strings" + "fmt" + "os" + "os/exec" + "strings" + + "codeberg.org/snonux/hexai/internal/textutil" ) // Enabled reports whether tmux status updates are enabled via env (default: on). func Enabled() bool { - v := strings.TrimSpace(os.Getenv("HEXAI_TMUX_STATUS")) - if v == "" { return true } - v = strings.ToLower(v) - return v == "1" || v == "true" || v == "yes" || v == "on" + v := strings.TrimSpace(os.Getenv("HEXAI_TMUX_STATUS")) + if v == "" { + return true + } + v = strings.ToLower(v) + return v == "1" || v == "true" || v == "yes" || v == "on" } // SetUserOption sets a global tmux user option like @hexai_status to value. func SetUserOption(key, value string) error { - if !Enabled() || !HasBinary() || !InSession() { return nil } - k := strings.TrimPrefix(strings.TrimSpace(key), "@") - if k == "" { return nil } - // Use set-option -g so it appears for all windows - return exec.Command("tmux", "set-option", "-g", "@"+k, value).Run() + if !Enabled() || !HasBinary() || !InSession() { + return nil + } + k := strings.TrimPrefix(strings.TrimSpace(key), "@") + if k == "" { + return nil + } + // Use set-option -g so it appears for all windows + return exec.Command("tmux", "set-option", "-g", "@"+k, value).Run() } // SetStatus is a convenience for setting @hexai_status. -func SetStatus(value string) error { return SetUserOption("hexai_status", value) } +func SetStatus(value string) error { return SetUserOption("hexai_status", applyTheme(value)) } + +// FormatLLMStatsStatus builds a compact tmux status string for LLM heartbeats. +// Example: "LLM:gpt-4.1 5r 0.8rpm in12k out34k" +func FormatLLMStatsStatus(model string, reqs int64, rpm float64, inBytes, outBytes int64) string { + return fmt.Sprintf("LLM:%s %dr %.1frpm in%s out%s", model, reqs, rpm, textutil.HumanBytes(inBytes), textutil.HumanBytes(outBytes)) +} + +// FormatLLMStatsStatusColored is like FormatLLMStatsStatus but includes provider and +// tmux color segments for readability. Uses up/down arrows for bytes. +// Example (with colors): "LLM:openai:gpt-4.1 ↑12k ↓34k 0.8rpm 5r" +func FormatLLMStatsStatusColored(provider, model string, reqs int64, rpm float64, inBytes, outBytes int64) string { + in := textutil.HumanBytes(inBytes) + out := textutil.HumanBytes(outBytes) + // Keep it compact; colorize prefix and arrows; use fg resets so a themed bg can persist. + // colour8 = dim grey, colour3 = yellow (up), colour2 = green (down) + return fmt.Sprintf( + "#[fg=colour8]LLM:#[fg=default]%s:%s #[fg=colour3]↑%s#[fg=default] #[fg=colour2]↓%s#[fg=default] %.1frpm %dr", + provider, model, in, out, rpm, reqs, + ) +} + +// FormatLLMStartStatus renders a short colored heartbeat at start/initialize time. +// Example: "LLM:openai:gpt-4.1 ⏳" +func FormatLLMStartStatus(provider, model string) string { + return fmt.Sprintf("#[fg=colour8]LLM:#[fg=default]%s:%s #[fg=colour11]⏳#[fg=default]", provider, model) +} +// applyTheme wraps the status string with a user-selected tmux style if requested. +// Set HEXAI_TMUX_STATUS_THEME=white-on-purple to get white-on-purple background. +func applyTheme(s string) string { + theme := strings.ToLower(strings.TrimSpace(os.Getenv("HEXAI_TMUX_STATUS_THEME"))) + // Allow explicit fg/bg override + fg := strings.TrimSpace(os.Getenv("HEXAI_TMUX_STATUS_FG")) + bg := strings.TrimSpace(os.Getenv("HEXAI_TMUX_STATUS_BG")) + if fg != "" || bg != "" { + if fg == "" { + fg = "default" + } + if bg == "" { + bg = "default" + } + return "#[fg=" + fg + ",bg=" + bg + "]" + s + "#[fg=default,bg=default]" + } + if theme == "white-on-purple" || theme == "purple" || theme == "magenta" || theme == "white-on-magenta" { + return "#[fg=white,bg=magenta]" + s + "#[fg=default,bg=default]" + } + if theme == "black-on-yellow" || theme == "yellow" || theme == "black-on-gold" { + return "#[fg=black,bg=yellow]" + s + "#[fg=default,bg=default]" + } + if theme == "white-on-blue" || theme == "blue" || theme == "white-on-navy" { + return "#[fg=white,bg=blue]" + s + "#[fg=default,bg=default]" + } + return s +} |
