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

@ -343,10 +343,10 @@ func (g *Gateway) handleLoginAPI(w http.ResponseWriter, r *http.Request) {
return
}
http.SetCookie(w, &http.Cookie{
Name: "gw_key",
Value: body.Key,
Path: "/",
MaxAge: 86400 * 30,
Name: "gw_key",
Value: body.Key,
Path: "/",
MaxAge: 86400 * 30,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
})
@ -456,7 +456,15 @@ func (g *Gateway) handleStatusAPI(w http.ResponseWriter, r *http.Request) {
"gateway_keys": ks,
}
if reqRole(r.Context()) == "admin" {
resp["sources"] = g.core.Registry().Status()
sts := g.core.Registry().Status()
recent := g.stats.SourceRecent(300)
for i := range sts {
if v, ok := recent[sts[i].Name]; ok {
sts[i].RecentOK = v[0]
sts[i].RecentErr = v[1]
}
}
resp["sources"] = sts
resp["adapters"] = g.core.ListAdapters()
}
writeJSON(w, http.StatusOK, resp)
@ -491,4 +499,4 @@ func writeJSON(w http.ResponseWriter, code int, v interface{}) {
if err := json.NewEncoder(w).Encode(v); err != nil {
log.Printf("[gateway] write json: %v", err)
}
}
}