v0.1.79 7970412

status.go RawHistoryFolder

1package telegram
2
3import (
4	"fmt"
5	"os"
6	"strings"
7
8	"github.com/patriceckhart/zot/internal/provider"
9)
10
11// StatusSnapshot is the small cross-host state bundle rendered for
12// Telegram /status replies.
13type StatusSnapshot struct {
14	Provider     string
15	Model        string
16	CWD          string
17	Usage        provider.Usage
18	Subscription bool
19	ContextUsed  int
20	ContextMax   int
21	Busy         bool
22	Queued       int
23}
24
25// FormatStatus renders the same compact model/usage/cost/context
26// information shown in the TUI status bar, plus the current directory.
27func FormatStatus(s StatusSnapshot) string {
28	providerName := strings.TrimSpace(s.Provider)
29	model := strings.TrimSpace(s.Model)
30	if providerName == "" {
31		providerName = "unknown"
32	}
33	if model == "" {
34		model = "unknown"
35	}
36
37	var stats []string
38	if s.Usage.InputTokens > 0 {
39		stats = append(stats, fmt.Sprintf("↑%s", formatTokens(s.Usage.InputTokens)))
40	}
41	if s.Usage.OutputTokens > 0 {
42		stats = append(stats, fmt.Sprintf("↓%s", formatTokens(s.Usage.OutputTokens)))
43	}
44	if s.Usage.CacheReadTokens > 0 {
45		stats = append(stats, fmt.Sprintf("R%s", formatTokens(s.Usage.CacheReadTokens)))
46	}
47	if s.Usage.CacheWriteTokens > 0 {
48		stats = append(stats, fmt.Sprintf("W%s", formatTokens(s.Usage.CacheWriteTokens)))
49	}
50	if s.Usage.CostUSD > 0 || s.Subscription {
51		cost := fmt.Sprintf("$%.3f", s.Usage.CostUSD)
52		if s.Subscription {
53			cost += " (sub)"
54		}
55		stats = append(stats, cost)
56	}
57	if ctx := contextUsage(s.ContextUsed, s.ContextMax); ctx != "" {
58		stats = append(stats, ctx)
59	}
60
61	line := fmt.Sprintf("(%s) %s", providerName, model)
62	if len(stats) > 0 {
63		line += "  " + strings.Join(stats, " ")
64	}
65
66	state := "idle"
67	if s.Busy {
68		state = "working"
69	}
70	lines := []string{line, "state: " + state}
71	if s.Queued > 0 {
72		lines = append(lines, fmt.Sprintf("queued: %d", s.Queued))
73	}
74	if cwd := shortenHome(strings.TrimSpace(s.CWD)); cwd != "" {
75		lines = append(lines, "cwd: "+cwd)
76	}
77	return strings.Join(lines, "\n")
78}
79
80func contextUsage(used, max int) string {
81	if max <= 0 {
82		if used <= 0 {
83			return ""
84		}
85		return formatTokens(used)
86	}
87	pct := float64(used) / float64(max) * 100
88	return fmt.Sprintf("%.1f%%/%s", pct, formatTokens(max))
89}
90
91func formatTokens(n int) string {
92	switch {
93	case n < 0:
94		return "0"
95	case n < 1000:
96		return fmt.Sprintf("%d", n)
97	case n < 10000:
98		return fmt.Sprintf("%.1fk", float64(n)/1000)
99	case n < 1_000_000:
100		return fmt.Sprintf("%dk", (n+500)/1000)
101	case n < 10_000_000:
102		return fmt.Sprintf("%.1fM", float64(n)/1_000_000)
103	default:
104		return fmt.Sprintf("%dM", (n+500_000)/1_000_000)
105	}
106}
107
108func shortenHome(path string) string {
109	home, err := os.UserHomeDir()
110	if err != nil || home == "" {
111		return path
112	}
113	if path == home {
114		return "~"
115	}
116	if strings.HasPrefix(path, home+string(os.PathSeparator)) {
117		return "~" + strings.TrimPrefix(path, home)
118	}
119	return path
120}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 477

↑↓ moveenter openesc close