fix(status): source column reflects real traffic + theme-aware tray menu

- api/status sources now carry recent_ok/recent_err (last 300s real gateway
  requests via Stats.SourceRecent) so a source actually serving traffic is
  never shown as down just because probe /models got rate-limited
- WebUI source status column repaints every 5s (no more frozen-at-first-
  render) with a manual refresh button; shows success rate + probe + cooldown
- tray menu status rows were enabled:false (GTK fixed light-grey, invisible
  on light themes) — now enabled with no-op click and nativeTheme listener
  rebuilds the menu on dark/light switches
- ignore local ops scripts (scripts/, machine-specific)
This commit is contained in:
2026-08-17 17:37:04 +08:00
parent 23bd9e5552
commit 8c5279b416
6 changed files with 141 additions and 32 deletions

View File

@ -26,7 +26,7 @@ type Req struct {
Compl int64 `json:"completion_tokens"`
// LatMs total handling time ms
LatMs int64 `json:"latency_ms"`
OK bool `json:"ok"`
OK bool `json:"ok"`
// Status http status code
Status int `json:"status"`
// Err short error message
@ -445,6 +445,33 @@ func (s *Stats) AuditRecords(from, to int64, key string) []Req {
return out
}
// SourceRecent counts real gateway requests per source within the last
// window (unix seconds). It reads only the in-memory ring, so it is cheap and
// reflects live traffic — used by /api/status so the source status column is
// driven by what actually happens, not just a probe.
func (s *Stats) SourceRecent(windowSec int64) map[string][2]int64 {
s.mu.Lock()
defer s.mu.Unlock()
cut := time.Now().Unix() - windowSec
out := map[string][2]int64{}
for _, r := range s.recs {
if r.Time/1000 < cut {
continue
}
if r.Source == "" {
continue
}
v := out[r.Source]
if r.OK {
v[0]++
} else {
v[1]++
}
out[r.Source] = v
}
return out
}
// Snapshot returns the whole dashboard payload; when key != "" the records
// and aggregate views are restricted to that gateway key.
func (s *Stats) Snapshot(limit int, key string) map[string]interface{} {
@ -506,4 +533,4 @@ func (s *Stats) Snapshot(limit int, key string) map[string]interface{} {
"by_status": bs,
"records": append([]Req(nil), recs...),
}
}
}