
OmniRoute 免费用量汇总 API 的 Catalog 数据源一致性修复free-tier summary 路由如何接入 Radar 实时目录【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline Copilot. Quota-aware auto-fallback, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute导读本文围绕仓库中changelog.d/fixes/11550-free-tier-summary-catalog-source.md记录的一项修复展开在 OmniRoute 网关中GET /api/free-tier/summary此前无论 Radar 实时 Feed 是否生效都只返回随版本冻结的 baseline 目录数据导致API 报告的免费用量与仪表盘展示的免费用量不一致。修复后该路由与仪表盘复用同一套目录解析逻辑getRadarCatalog在响应中显式声明本次应答由哪个 Catalog 来源baseline或radar-overlay提供、以及该来源真实的构建/整理日期同时将支持者密钥supporter-key专属的 live Feed 数据严格限制给本实例已认证调用方。读完本文你将掌握该 API 的完整响应契约、数据源裁决规则与鉴权边界并能直接通过源码与单测验证这些行为。一、问题背景一个免费额度问题两个互相矛盾的答案OmniRoute 的免费额度体系有一套以目录catalog为唯一事实源的展示机制随版本冻结的 baseline 目录手工维护、随 release 发布的FREE_MODEL_BUDGETS整理日期记录为FREE_CATALOG_CURATED_AT见 open-sse/config/freeModelCatalog.data.ts。Radar 实时覆盖层overlay当RADAR_ENABLED开关打开且本地已同步 feed 缓存时会通过getRadarCatalog()将 feed 中的新模型/新额度叠加在 baseline 之上仪表盘各页面如 Free-Tier Budget 卡片、free-tiers 页面都读取这份解析后的目录。修复前的缺陷正如该 changelog 所述summary 路由始终回答 release-frozen 的 baseline 数字却带着过期的整理日期而 Radar overlay 又在后台刷新同一份目录给仪表盘看。结果是——两个入口、一个问题的两个不同答案且声称自己有日期的那个入口恰恰是数据最旧的那个。相关分析也完整记录在单测文件头注释中见 tests/unit/free-tier-summary-radar-overlay.test.ts。这一点还叠加了一个语义陷阱standalone 构建在部署时会把所有文件时间戳重写如果实现用文件 mtime 冒充目录更新时间就会把一份过期目录宣传成刚更新过。因此修复的核心原则是只报真实应答来源自己的日期。二、修复方案与仪表盘共用同一套 Catalog 解析修复的实现集中在 src/app/api/free-tier/summary/route.ts其核心逻辑为// Same catalog resolution as the dashboard screens: one source of // truth, with meta null meaning the baseline answered (flag off, no // cache, or corrupt cache). const { entries, meta } getRadarCatalog(); const serveOverlay meta ! null (meta.tier ! live || (await isAuthenticated(req))); const totals serveOverlay ? computeFreeModelTotals({ excludeTosAvoid, entries: entries.map(toBudgetEntry) }) : computeFreeModelTotals({ excludeTosAvoid });2.1 解析函数getRadarCatalog的裁决规则getRadarCatalog定义在 src/lib/radar/index.ts返回{ entries, meta }其中meta null表示 baseline 应答。源码注释明确列出 baseline 生效的三种情形RADAR_ENABLED开关关闭本地没有任何 feed 缓存缓存存在但已损坏payload 无法解析/签名校验失败。当 overlay 应答时meta携带version、tiercommunity/live与generatedAtfeed 自身的构建日期其中generatedAt允许为null代表迁移前写入的旧缓存行没有记录构建日期这一事实状态。2.2 目录的合并与形状保持当 overlay 生效时路由先将 merge 后的条目经toBudgetEntry()投影回 baseline 的FreeModelBudget形状再送入汇总这样 overlay 内部的额外字段origin、provenance、capabilities 等不会泄漏到对外契约中——无论哪个来源应答公开的 JSON 结构完全一致。投影过程还有一个关键细节hardStopGuaranteed是 baseline 手工维护的、feed 不携带的事实因此路由预先建立provider:modelId→ 布尔值的映射HARD_STOP_BY_KEY在 overlay 应答时从 baseline 回读补上避免降级丢失。见 src/app/api/free-tier/summary/route.ts。汇总函数本身computeFreeModelTotals位于 open-sse/config/freeModelCatalog.ts负责 per-model 池去重每个共享池只计一次、excludeTosAvoid过滤排除tos avoid或enabled false的条目、计算steadyRecurringTokens/firstMonthRealisticTokens/boostMonthlyTokens/uncappedProviders等输出字段。三、诚实标注catalogSource与catalogUpdatedAt修复引入两个新字段用于回答这是谁的数据、数据有多新字段取值含义catalogSourcebaselinerelease-frozen 目录应答开关关、无缓存、缓存损坏或匿名访问 live feed 被拒catalogSourceradar-overlayRadar feed 目录应答解析后的实时目录catalogUpdatedAtbaseline 路径取手工维护常量FREE_CATALOG_CURATED_AT绝不取文件 mtimecatalogUpdatedAtoverlay 路径取meta.generatedAt即feed 自己的构建日期若为迁移前的旧缓存行则为null未知就保持未知绝不用下载时刻fetchedAt冒充源码实现见 src/app/api/free-tier/summary/route.ts。单测 tests/unit/free-tier-summary-route.test.ts 专门断言catalogUpdatedAt必须等于FREE_CATALOG_CURATED_AT、必须是可解析的日期且不得晚于当前时间——因为它只允许报告真实的整理日期而不能是构建时间戳。由此调用方例如仪表盘预算卡片可以直接区分显示的额度是跟随 release 冻结的基线还是已随 Radar feed 实时刷新的版本。四、鉴权边界supporter-key 的 live Feed 不做公开转发Radar feed 服务器在下载时刻就决定了内容等级community feed 是免费公开目录live feed 是支持者密钥supporter-key专属内容。本实例可以合法地重新供给自己持有的内容但当实例暴露在公网时绝不能变成付费内容的免费中继。因此修复后的 entitlement 规则是community tier→ 供给所有调用方匿名与已认证均可见因为这是公共免费 feedlive tier→ 仅供给本实例已认证的调用方经isAuthenticated(req)判定匿名调用方回退到 release-frozen 的 baseline开关关闭 / 无缓存 / 缓存损坏→ 行为与修复前完全一致baseline。对应实现即serveOverlay meta ! null (meta.tier ! live || (await isAuthenticated(req)))认证工具来自 src/shared/utils/apiAuth.ts。这一边界被 tests/unit/free-tier-summary-radar-overlay.test.ts 全面覆盖包括以下场景开关关闭 → baseline 应答诚实打上catalogSource: baselinecommunity 匿名 / 已认证 → 均返回 overlaycatalogUpdatedAt等于 feed 构建日期GEN_AT且不等于下载时刻FETCHED_ATfeed 中enabled: false的条目不进入 totals 与perModel迁移前缓存行无generatedAt→ 返回 overlay 但catalogUpdatedAt: nulllive 匿名 → baselinelive 已认证 → overlay本实例合法持有的额度损坏缓存 → baseline 兜底契约不变。五、完整的响应契约GET /api/free-tier/summary返回200JSON测试见 tests/unit/free-tier-summary-route.test.ts。核心字段包括steadyRecurringTokens文档化、按池去重后的月度经常性 token 总额测试断言 ≥ 10 亿是可对外宣传的稳数字firstMonthRealisticTokenssteady 一次性注册赠额仅首月恒不小于steadyRecurringTokensusedThisMonth本月已用 token来自sumUsageTokensThisMonth()见 src/lib/db/usageSummary.tsremainingmax(0, steadyRecurringTokens - usedThisMonth)boostMonthlyTokensdeposit-unlock 提升如 OpenRouter $10 充值把免费池从 50 提至 1000 req/day 的约 2400 万/月单独报告、绝不并入 steady测试断言boostMonthlyTokens steadyRecurringTokens详见 open-sse/config/freeModelCatalog.ts 的FREE_TIER_BOOSTSuncappedProviders永久免费但无公开 token 上限的供应商列表列出但不求和perModelper-model 条目数组≥ 400 项覆盖上千模型形状同FreeModelBudget且携带enabledmodelCount、headline含 free tokens/month等展示字段noCredentialProviders在服务端算好再下发——若在客户端推导会把整个 provider REGISTRY 打进浏览器 bundle见 src/shared/utils/providerCredentialRequirement.tscatalogSource/catalogUpdatedAt本修复新增的来源与日期标注响应体中不包含任何at /形式的堆栈痕迹防止异常路径泄露两处测试均有断言。查询参数excludeTosAvoid1会过滤tos avoid的模型测试确认该参数在 baseline 路径与 overlay 路径上都生效但它只影响 summary 视图不影响全局路由决策。CORS 头允许*源、仅放行GET, OPTIONS并有对应的OPTIONS预检处理器见 src/app/api/free-tier/summary/route.ts。六、数据流全貌与仪表盘消费方修复后的数据流可归纳为一条主线dashboard 各页面FreeBudgetCard 等与/api/free-tier/summary走同一条getRadarCatalog()→computeFreeModelTotals()链路对外只通过catalogSource区分底座。仪表盘侧的消费组件见 src/app/(dashboard)/dashboard/usage/components/FreeBudgetCard.tsx/dashboard/usage/components/FreeBudgetCard.tsx)汇总页面见 src/app/(dashboard)/dashboard/free-tiers/page.tsx/dashboard/free-tiers/page.tsx)。值得注意的设计分界统计/展示与决策刻意读不同的源。展示使用baseline 叠加 Radar feed 的解析目录决策模型导入、auto/*路由、GET /v1/models、浏览器预览则只使用随包发布的FREE_MODEL_BUDGETS加上本地启发式规则:free后缀、零定价、grantsFreeAccess见 docs/reference/FREE_TIERS.md 的 Two regimes 章节与 src/shared/utils/freeModels.ts。展示可以随 feed 实时变好决策必须离线可复现、且浏览器与服务端答案一致——本次修复不改变这一分界只消除展示链路内部的两个入口两个答案。七、结论与验证清单11550这一修复把 free-tier summary 从永远报告冻结数字 过期日期改为随 Radar feed 刷新 诚实标注来源与构建日期同时守住了一条关键红线支持者专属的 live Feed 只服务已认证调用方匿名与公开实例绝不转发付费内容。如果你想在本地复现或回归验证可直接运行仓库中的两个单测文件tests/unit/free-tier-summary-route.test.ts —— 响应契约、去重总量、excludeTosAvoid、日期诚实性、无堆栈泄露tests/unit/free-tier-summary-radar-overlay.test.ts —— overlay/baseline 裁决矩阵、community/live 鉴权矩阵、迁移旧缓存与损坏缓存兜底。结合 src/app/api/free-tier/summary/route.ts、src/lib/radar/index.ts 与 open-sse/config/freeModelCatalog.ts 三处源码阅读即可完整掌握这套单一事实源 诚实溯源的实现。【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline Copilot. Quota-aware auto-fallback, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考