feat: show available reset credits

This commit is contained in:
2026-08-22 09:59:10 +08:00
parent 45ceeee936
commit 6a711c1fff
12 changed files with 201 additions and 21 deletions
+35 -2
View File
@@ -8,6 +8,7 @@ import (
"net/http"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
@@ -229,6 +230,7 @@ func (a *App) dashboardAPI(w http.ResponseWriter, r *http.Request) {
func publicDashboard(d Dashboard) Dashboard {
d.Account.Email = nil
d.Account.AuthMode = nil
d.ResetCredits = nil
d.LastError = ""
return d
}
@@ -489,10 +491,12 @@ func (a *App) syncAccount(ctx context.Context, id int64) error {
d.Account.AuthMode = &ar.Account.Type
}
var lr struct {
RateLimits *rawLimit `json:"rateLimits"`
By map[string]rawLimit `json:"rateLimitsByLimitId"`
RateLimits *rawLimit `json:"rateLimits"`
By map[string]rawLimit `json:"rateLimitsByLimitId"`
ResetCredits *rawResetCredits `json:"rateLimitResetCredits"`
}
if e := rt.client.Call(ctx, "account/rateLimits/read", map[string]any{}, &lr); e == nil {
d.ResetCredits = normalizeResetCredits(lr.ResetCredits)
if len(lr.By) > 0 {
for _, x := range lr.By {
d.Limits = append(d.Limits, flattenLimit(x)...)
@@ -605,6 +609,35 @@ type rawLimit struct {
Secondary *LimitWindow `json:"secondary"`
}
type rawResetCredits struct {
AvailableCount int `json:"availableCount"`
Credits []rawResetCredit `json:"credits"`
}
type rawResetCredit struct {
ExpiresAt *int64 `json:"expiresAt"`
}
func normalizeResetCredits(raw *rawResetCredits) *ResetCreditsSummary {
if raw == nil || raw.AvailableCount <= 0 {
return nil
}
expiresAt := make([]int64, 0, len(raw.Credits))
for _, credit := range raw.Credits {
if credit.ExpiresAt != nil && *credit.ExpiresAt > 0 {
expiresAt = append(expiresAt, *credit.ExpiresAt)
}
}
sort.Slice(expiresAt, func(i, j int) bool { return expiresAt[i] < expiresAt[j] })
uniqueExpiresAt := expiresAt[:0]
for _, value := range expiresAt {
if len(uniqueExpiresAt) == 0 || uniqueExpiresAt[len(uniqueExpiresAt)-1] != value {
uniqueExpiresAt = append(uniqueExpiresAt, value)
}
}
return &ResetCreditsSummary{AvailableCount: raw.AvailableCount, ExpiresAt: uniqueExpiresAt}
}
func currentTokenCycle(limits []LimitBucket, usage []UsagePoint, fetchedAt int64) *TokenCycle {
current := LimitBucket{}
found := false