feat: Add validation and account management functionality (#21)

* feat: Add validation and account management functionality

- Add validation for clientID and clientSecret in refreshOIDCToken function
- Add weight field for load balancing priority in Account struct
- Implement weighted轮询策略以根据账号权重分配选择概率。
- Add batch account management functionality including enabling, disabling, refreshing, and retrieving account details.
- Update Kiro API version and adjust user agent strings to reflect new version numbers.
- Update Kiro version and modify user agent strings and header settings.
- Refactor model mapping to an ordered list for precise key matching.
- Add account bulk actions and filtering toolbar to index.html

* feat: Add logic to skip accounts with exhausted usage limits

- Add logic to skip accounts with exhausted usage limits when selecting the next account.
This commit is contained in:
hkxiaoyao
2026-02-23 21:47:17 +08:00
committed by GitHub
parent d71bf09dde
commit ad7aabd554
7 changed files with 323 additions and 23 deletions

View File

@@ -36,13 +36,25 @@ func GetPool() *AccountPool {
}
// Reload 从配置重新加载账号
// 构建加权列表weight<=1 出现 1 次weight>=2 出现 weight 次
func (p *AccountPool) Reload() {
p.mu.Lock()
defer p.mu.Unlock()
p.accounts = config.GetEnabledAccounts()
enabled := config.GetEnabledAccounts()
var weighted []config.Account
for _, a := range enabled {
w := a.Weight
if w < 1 {
w = 1
}
for j := 0; j < w; j++ {
weighted = append(weighted, a)
}
}
p.accounts = weighted
}
// GetNext 获取下一个可用账号(轮询)
// GetNext 获取下一个可用账号(加权轮询)
func (p *AccountPool) GetNext() *config.Account {
p.mu.RLock()
defer p.mu.RUnlock()
@@ -53,30 +65,47 @@ func (p *AccountPool) GetNext() *config.Account {
now := time.Now()
n := len(p.accounts)
seen := make(map[string]bool)
// 轮询查找可用账号
// 加权轮询查找可用账号
for i := 0; i < n; i++ {
idx := atomic.AddUint64(&p.currentIndex, 1) % uint64(n)
acc := &p.accounts[idx]
if seen[acc.ID] {
continue
}
// 跳过冷却中的账号
if cooldown, ok := p.cooldowns[acc.ID]; ok && now.Before(cooldown) {
seen[acc.ID] = true
continue
}
// 跳过即将过期的 Token
if acc.ExpiresAt > 0 && time.Now().Unix() > acc.ExpiresAt-300 {
seen[acc.ID] = true
continue
}
// 跳过额度已用尽的账号(适用于所有订阅类型)
if acc.UsageLimit > 0 && acc.UsageCurrent >= acc.UsageLimit {
seen[acc.ID] = true
continue
}
return acc
}
// 无可用账号,返回冷却时间最短的
// 无可用账号,返回冷却时间最短的(排除额度用尽的)
var best *config.Account
var earliest time.Time
for i := range p.accounts {
acc := &p.accounts[i]
// 额度用尽的账号不作为 fallback
if acc.UsageLimit > 0 && acc.UsageCurrent >= acc.UsageLimit {
continue
}
if cooldown, ok := p.cooldowns[acc.ID]; ok {
if best == nil || cooldown.Before(earliest) {
best = acc