|
|
|
@@ -53,6 +53,7 @@ type AccountHandler struct {
|
|
|
|
|
concurrencyService *service.ConcurrencyService
|
|
|
|
|
crsSyncService *service.CRSSyncService
|
|
|
|
|
sessionLimitCache service.SessionLimitCache
|
|
|
|
|
rpmCache service.RPMCache
|
|
|
|
|
tokenCacheInvalidator service.TokenCacheInvalidator
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -69,6 +70,7 @@ func NewAccountHandler(
|
|
|
|
|
concurrencyService *service.ConcurrencyService,
|
|
|
|
|
crsSyncService *service.CRSSyncService,
|
|
|
|
|
sessionLimitCache service.SessionLimitCache,
|
|
|
|
|
rpmCache service.RPMCache,
|
|
|
|
|
tokenCacheInvalidator service.TokenCacheInvalidator,
|
|
|
|
|
) *AccountHandler {
|
|
|
|
|
return &AccountHandler{
|
|
|
|
@@ -83,6 +85,7 @@ func NewAccountHandler(
|
|
|
|
|
concurrencyService: concurrencyService,
|
|
|
|
|
crsSyncService: crsSyncService,
|
|
|
|
|
sessionLimitCache: sessionLimitCache,
|
|
|
|
|
rpmCache: rpmCache,
|
|
|
|
|
tokenCacheInvalidator: tokenCacheInvalidator,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -154,6 +157,7 @@ type AccountWithConcurrency struct {
|
|
|
|
|
// 以下字段仅对 Anthropic OAuth/SetupToken 账号有效,且仅在启用相应功能时返回
|
|
|
|
|
CurrentWindowCost *float64 `json:"current_window_cost,omitempty"` // 当前窗口费用
|
|
|
|
|
ActiveSessions *int `json:"active_sessions,omitempty"` // 当前活跃会话数
|
|
|
|
|
CurrentRPM *int `json:"current_rpm,omitempty"` // 当前分钟 RPM 计数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (h *AccountHandler) buildAccountResponseWithRuntime(ctx context.Context, account *service.Account) AccountWithConcurrency {
|
|
|
|
@@ -189,6 +193,12 @@ func (h *AccountHandler) buildAccountResponseWithRuntime(ctx context.Context, ac
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if h.rpmCache != nil && account.GetBaseRPM() > 0 {
|
|
|
|
|
if rpm, err := h.rpmCache.GetRPM(ctx, account.ID); err == nil {
|
|
|
|
|
item.CurrentRPM = &rpm
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return item
|
|
|
|
@@ -231,9 +241,10 @@ func (h *AccountHandler) List(c *gin.Context) {
|
|
|
|
|
concurrencyCounts = make(map[int64]int)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 识别需要查询窗口费用和会话数的账号(Anthropic OAuth/SetupToken 且启用了相应功能)
|
|
|
|
|
// 识别需要查询窗口费用、会话数和 RPM 的账号(Anthropic OAuth/SetupToken 且启用了相应功能)
|
|
|
|
|
windowCostAccountIDs := make([]int64, 0)
|
|
|
|
|
sessionLimitAccountIDs := make([]int64, 0)
|
|
|
|
|
rpmAccountIDs := make([]int64, 0)
|
|
|
|
|
sessionIdleTimeouts := make(map[int64]time.Duration) // 各账号的会话空闲超时配置
|
|
|
|
|
for i := range accounts {
|
|
|
|
|
acc := &accounts[i]
|
|
|
|
@@ -245,12 +256,24 @@ func (h *AccountHandler) List(c *gin.Context) {
|
|
|
|
|
sessionLimitAccountIDs = append(sessionLimitAccountIDs, acc.ID)
|
|
|
|
|
sessionIdleTimeouts[acc.ID] = time.Duration(acc.GetSessionIdleTimeoutMinutes()) * time.Minute
|
|
|
|
|
}
|
|
|
|
|
if acc.GetBaseRPM() > 0 {
|
|
|
|
|
rpmAccountIDs = append(rpmAccountIDs, acc.ID)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 并行获取窗口费用和活跃会话数
|
|
|
|
|
// 并行获取窗口费用、活跃会话数和 RPM 计数
|
|
|
|
|
var windowCosts map[int64]float64
|
|
|
|
|
var activeSessions map[int64]int
|
|
|
|
|
var rpmCounts map[int64]int
|
|
|
|
|
|
|
|
|
|
// 获取 RPM 计数(批量查询)
|
|
|
|
|
if len(rpmAccountIDs) > 0 && h.rpmCache != nil {
|
|
|
|
|
rpmCounts, _ = h.rpmCache.GetRPMBatch(c.Request.Context(), rpmAccountIDs)
|
|
|
|
|
if rpmCounts == nil {
|
|
|
|
|
rpmCounts = make(map[int64]int)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取活跃会话数(批量查询,传入各账号的 idleTimeout 配置)
|
|
|
|
|
if len(sessionLimitAccountIDs) > 0 && h.sessionLimitCache != nil {
|
|
|
|
@@ -311,6 +334,13 @@ func (h *AccountHandler) List(c *gin.Context) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加 RPM 计数(仅当启用时)
|
|
|
|
|
if rpmCounts != nil {
|
|
|
|
|
if rpm, ok := rpmCounts[acc.ID]; ok {
|
|
|
|
|
item.CurrentRPM = &rpm
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result[i] = item
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -453,6 +483,8 @@ func (h *AccountHandler) Create(c *gin.Context) {
|
|
|
|
|
response.BadRequest(c, "rate_multiplier must be >= 0")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// base_rpm 输入校验:负值归零,超过 10000 截断
|
|
|
|
|
sanitizeExtraBaseRPM(req.Extra)
|
|
|
|
|
|
|
|
|
|
// 确定是否跳过混合渠道检查
|
|
|
|
|
skipCheck := req.ConfirmMixedChannelRisk != nil && *req.ConfirmMixedChannelRisk
|
|
|
|
@@ -522,6 +554,8 @@ func (h *AccountHandler) Update(c *gin.Context) {
|
|
|
|
|
response.BadRequest(c, "rate_multiplier must be >= 0")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// base_rpm 输入校验:负值归零,超过 10000 截断
|
|
|
|
|
sanitizeExtraBaseRPM(req.Extra)
|
|
|
|
|
|
|
|
|
|
// 确定是否跳过混合渠道检查
|
|
|
|
|
skipCheck := req.ConfirmMixedChannelRisk != nil && *req.ConfirmMixedChannelRisk
|
|
|
|
@@ -904,6 +938,9 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// base_rpm 输入校验:负值归零,超过 10000 截断
|
|
|
|
|
sanitizeExtraBaseRPM(item.Extra)
|
|
|
|
|
|
|
|
|
|
skipCheck := item.ConfirmMixedChannelRisk != nil && *item.ConfirmMixedChannelRisk
|
|
|
|
|
|
|
|
|
|
account, err := h.adminService.CreateAccount(ctx, &service.CreateAccountInput{
|
|
|
|
@@ -1048,6 +1085,8 @@ func (h *AccountHandler) BulkUpdate(c *gin.Context) {
|
|
|
|
|
response.BadRequest(c, "rate_multiplier must be >= 0")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// base_rpm 输入校验:负值归零,超过 10000 截断
|
|
|
|
|
sanitizeExtraBaseRPM(req.Extra)
|
|
|
|
|
|
|
|
|
|
// 确定是否跳过混合渠道检查
|
|
|
|
|
skipCheck := req.ConfirmMixedChannelRisk != nil && *req.ConfirmMixedChannelRisk
|
|
|
|
@@ -1706,3 +1745,22 @@ func (h *AccountHandler) BatchRefreshTier(c *gin.Context) {
|
|
|
|
|
func (h *AccountHandler) GetAntigravityDefaultModelMapping(c *gin.Context) {
|
|
|
|
|
response.Success(c, domain.DefaultAntigravityModelMapping)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sanitizeExtraBaseRPM 对 extra map 中的 base_rpm 值进行范围校验和归一化。
|
|
|
|
|
// 负值归零,超过 10000 截断为 10000。extra 为 nil 或不含 base_rpm 时无操作。
|
|
|
|
|
func sanitizeExtraBaseRPM(extra map[string]any) {
|
|
|
|
|
if extra == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
raw, ok := extra["base_rpm"]
|
|
|
|
|
if !ok {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
v := service.ParseExtraInt(raw)
|
|
|
|
|
if v < 0 {
|
|
|
|
|
v = 0
|
|
|
|
|
} else if v > 10000 {
|
|
|
|
|
v = 10000
|
|
|
|
|
}
|
|
|
|
|
extra["base_rpm"] = v
|
|
|
|
|
}
|
|
|
|
|