From 88103657fb230bb41217a06aa5602ae23e7acb8b Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 17 Sep 2025 21:33:45 +0300 Subject: =?UTF-8?q?feat(stats,tmux):=20global=20=CE=A3@window=20stats=20ac?= =?UTF-8?q?ross=20processes=20with=20flocked=20cache;=20width=20mitigation?= =?UTF-8?q?=20(narrow/maxlen);=20configurable=20[stats]=20window=5Fminutes?= =?UTF-8?q?;=20robust=20coverage=20parsing;=20docs=20update\n\n-=20Add=20i?= =?UTF-8?q?nternal/stats=20with=20windowed=20event=20cache=20+=20flock=20+?= =?UTF-8?q?=20atomic=20writes\n-=20Wire=20stats=20into=20LSP/CLI/Tmux=20Ac?= =?UTF-8?q?tion;=20tmux=20shows=20=CE=A3@window=20with=20per-model=20tail\?= =?UTF-8?q?n-=20HEXAI=5FTMUX=5FSTATUS=5FNARROW=20and=20HEXAI=5FTMUX=5FSTAT?= =?UTF-8?q?US=5FMAXLEN=20for=20width=20control\n-=20Add=20[stats]=20window?= =?UTF-8?q?=5Fminutes=20to=20config=20and=20apply=20on=20startup\n-=20Impr?= =?UTF-8?q?ove=20Magefile=20coverage=20handling;=20add=20tests=20to=20lift?= =?UTF-8?q?=20coverage=20>85%\n-=20Update=20docs/tmux.md=20and=20config=20?= =?UTF-8?q?example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/lsp/handlers_utils.go | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'internal/lsp/handlers_utils.go') diff --git a/internal/lsp/handlers_utils.go b/internal/lsp/handlers_utils.go index 15f0174..43bfdc8 100644 --- a/internal/lsp/handlers_utils.go +++ b/internal/lsp/handlers_utils.go @@ -8,6 +8,7 @@ import ( "codeberg.org/snonux/hexai/internal/llm" "codeberg.org/snonux/hexai/internal/logging" + "codeberg.org/snonux/hexai/internal/stats" "codeberg.org/snonux/hexai/internal/textutil" tmx "codeberg.org/snonux/hexai/internal/tmux" ) @@ -59,15 +60,29 @@ func (s *Server) logLLMStats() { if mins <= 0 { mins = 0.001 } - rpm := float64(reqs) / mins + rpmLocal := float64(reqs) / mins sentPerMin := float64(sentTot) / mins recvPerMin := float64(recvTot) / mins - logging.Logf("lsp ", "llm stats reqs=%d avg_sent=%d avg_recv=%d sent_total=%d recv_total=%d rpm=%.2f sent_per_min=%.0f recv_per_min=%.0f", reqs, avgSent, avgRecv, sentTot, recvTot, rpm, sentPerMin, recvPerMin) - // Best-effort tmux status update with a compact stats heartbeat - if s.llmClient != nil { - model := s.llmClient.DefaultModel() + // Log local process counters + logging.Logf("lsp ", "llm stats (local) reqs=%d avg_sent=%d avg_recv=%d sent_total=%d recv_total=%d rpm=%.2f sent_per_min=%.0f recv_per_min=%.0f", reqs, avgSent, avgRecv, sentTot, recvTot, rpmLocal, sentPerMin, recvPerMin) + // Global snapshot for tmux status + snap, err := stats.TakeSnapshot() + if err == nil && s.llmClient != nil { provider := s.llmClient.Name() - status := tmx.FormatLLMStatsStatusColored(provider, model, reqs, rpm, sentTot, recvTot) + model := s.llmClient.DefaultModel() + // Per-scope rpm estimated from window + scopeReqs := int64(0) + if pe, ok := snap.Providers[provider]; ok { + if mc, ok2 := pe.Models[model]; ok2 { + scopeReqs = mc.Reqs + } + } + minsWin := snap.Window.Minutes() + if minsWin <= 0 { + minsWin = 0.001 + } + scopeRPM := float64(scopeReqs) / minsWin + status := tmx.FormatGlobalStatusColored(snap.Global.Reqs, snap.RPM, snap.Global.Sent, snap.Global.Recv, provider, model, scopeRPM, scopeReqs, snap.Window) _ = tmx.SetStatus(status) } } @@ -151,6 +166,10 @@ func (s *Server) chatWithStats(ctx context.Context, msgs []llm.Message, opts ... return "", err } s.incRecvCounters(len(txt)) + // Update global stats cache + if s.llmClient != nil { + _ = stats.Update(ctx, s.llmClient.Name(), s.llmClient.DefaultModel(), sent, len(txt)) + } s.logLLMStats() return txt, nil } -- cgit v1.2.3