feat(api-keys): add all-model weekly cost limit - #1186
Open
sxin0 wants to merge 4 commits into
Open
Conversation
新增 weeklyCostLimit 字段,对 API Key 的所有模型请求(含 Claude/GPT/Gemini/Bedrock 等) 统一计费并按周限额。原有 weeklyOpusCostLimit 仅对 Claude 模型生效的行为保持不变, 两个限额独立校验,共享 weeklyResetDay/Hour 重置周期。 - redis: 新增 getWeeklyCost / incrementWeeklyCost / setWeeklyCost (usage:weekly:<id>:<period>) - apiKeyService: recordWeeklyCost 无模型/账户过滤,在 recordUsage* 中追加调用 - auth: Claude 周限制检查后追加全模型检查,超限返回 402 weekly_cost_limit_exceeded - admin/apiKeys: create/update/batchUpdate/getKeyById 全部支持 weeklyCostLimit - 前端 6 个组件镜像 weeklyOpusCostLimit UI,新增独立进度条和输入框
weeklyCost (全模型周费用) 同样需要在重启后立即可用,否则 weeklyCostLimit 会被 当前周已经发生的请求绕过。改造 weeklyClaudeCostInitService 在单次 SCAN 中 同时回填两个 bucket: - 拿掉准备阶段的 isClaudeFamilyModel 过滤,全模型条目都进入处理 - Opus bucket 保留原有 isClaudeFamilyModel + OPUS_ACCOUNT_TYPES 过滤,行为不变 - 全模型 bucket 不做过滤,新增 inferAnyAccountType 覆盖 openai/gemini/bedrock/droid 等账户类型;推断不到 account 时退回 realCost(serviceRatesService.getService 会按 model fallback) - backfillSingleKey 同样双写 setWeeklyOpusCost + setWeeklyCost - done 标记 key 从 init:weekly_opus_cost 升级到 init:weekly_cost,确保升级后 第一次启动会重新回填,把两个 bucket 都填上 - app.js / admin/apiKeys.js 调用入口(函数名 backfillCurrentWeekClaudeCosts / backfillSingleKey)保持不变
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
weeklyCostLimit字段,对 API Key 的所有模型请求(Claude/GPT/Gemini/Bedrock/Droid 等)统一按周限额weeklyOpusCostLimit(仅 Claude 生效)行为保持不变,两个限额独立校验weeklyResetDay/weeklyResetHour重置周期,前端无需新增重置选择器Motivation
当前
weeklyOpusCostLimit只对 Claude 系列模型 +claude-official/claude-console/ccr三种账户类型生效(apiKeyService.recordOpusCost双重过滤)。GPT、Gemini、Bedrock 等模型既不累加也不被校验,无法对 API Key 设置跨模型的统一周预算。Changes
Backend
src/models/redis.js: 新增getWeeklyCost/incrementWeeklyCost/setWeeklyCost,独立 Redis keyusage:weekly:{keyId}:{period}+usage:real:weekly:...,14 天 TTL;batchGetApiKeyStatspipeline 扩展第 15 个字段src/services/apiKeyService.js: 新增recordWeeklyCost(无模型/账户过滤),在recordUsage/recordUsageWithDetails中追加调用;createApiKey/validateApiKey/字段白名单/3 个 enrichment 路径全部镜像src/services/weeklyClaudeCostInitService.js: 单次 SCAN 双写两个 bucketisClaudeFamilyModel + OPUS_ACCOUNT_TYPES过滤,行为完全不变inferAnyAccountType覆盖 openai/gemini/bedrock/azure-openai/droid;推断不到时退回 realCost(serviceRatesService.getService按 model fallback)backfillSingleKey同样双写(reset day/hour 变更时两个 bucket 一起回填)init:weekly_opus_cost:<date>:done升级为init:weekly_cost:<date>:done,确保升级后第一次启动会重新回填把全模型 bucket 也填上app.js、admin/apiKeys.js)函数名保持不变src/middleware/auth.js: Claude 周限制检查之后追加全模型检查,超限返回 402weekly_cost_limit_exceededsrc/routes/admin/apiKeys.js: 8 处 create/update/batchUpdate/getKeyById 全部支持weeklyCostLimit,校验非负数src/routes/apiStats.js:limitspayload 加weeklyCostLimit/weeklyCostFrontend
Design Notes
weeklyOpusCostLimit字段语义和存储不变,完全向后兼容usage:*:model:daily:*daily usage key,单次 SCAN 同时填两个 bucket,扫描开销不增Test Plan