feat: show current-cycle token totals

This commit is contained in:
2026-08-14 11:07:46 +08:00
parent 1ec9001387
commit bf37999833
12 changed files with 254 additions and 19 deletions
+53
View File
@@ -460,6 +460,7 @@ func (a *App) syncAccount(ctx context.Context, id int64) error {
d.Usage = append(d.Usage, p)
_, _ = a.store.DB.Exec("INSERT INTO daily_usage(account_id,date,total_tokens,fetched_at) VALUES(?,?,?,?) ON CONFLICT(account_id,date) DO UPDATE SET total_tokens=excluded.total_tokens,fetched_at=excluded.fetched_at", id, x.StartDate, x.Tokens, d.FetchedAt)
}
d.CurrentCycle = currentTokenCycle(d.Limits, d.Usage, d.FetchedAt)
}
resetDetected, e := a.storeLimitSnapshots(d)
if e != nil {
@@ -530,6 +531,58 @@ type rawLimit struct {
Secondary *LimitWindow `json:"secondary"`
}
func currentTokenCycle(limits []LimitBucket, usage []UsagePoint, fetchedAt int64) *TokenCycle {
current := LimitBucket{}
found := false
for _, limit := range limits {
if limit.WindowDurationMinutes <= 0 || limit.ResetsAt <= fetchedAt {
continue
}
if !found || betterTokenCycleLimit(limit, current) {
current = limit
found = true
}
}
if !found {
return nil
}
startedAt := current.ResetsAt - int64(current.WindowDurationMinutes)*60
startDate := time.Unix(startedAt, 0).UTC().Format("2006-01-02")
endDate := time.Unix(fetchedAt, 0).UTC().Format("2006-01-02")
var total int64
for _, point := range usage {
if point.Date < startDate || point.Date > endDate {
continue
}
if _, err := time.Parse("2006-01-02", point.Date); err != nil {
continue
}
total += point.TotalTokens
}
return &TokenCycle{
LimitID: current.LimitID,
WindowType: current.WindowType,
WindowDurationMinutes: current.WindowDurationMinutes,
StartedAt: startedAt,
ResetsAt: current.ResetsAt,
TotalTokens: total,
}
}
func betterTokenCycleLimit(candidate, current LimitBucket) bool {
if candidate.WindowDurationMinutes != current.WindowDurationMinutes {
return candidate.WindowDurationMinutes > current.WindowDurationMinutes
}
if candidate.WindowType != current.WindowType {
return candidate.WindowType == "secondary"
}
if candidate.LimitID != current.LimitID {
return candidate.LimitID < current.LimitID
}
return candidate.ResetsAt > current.ResetsAt
}
func flattenLimit(x rawLimit) []LimitBucket {
out := []LimitBucket{}
if x.Primary != nil {