AI 价格中心
配图占位:本节用于在后续视觉评审中插入「价格中心」页截图(4 Tab:价格矩阵 / 未设置价格 / 模板库 / 修订时间线;矩阵 8 列 + Tab 计数 badge + 未设置价格 badge 用警示色;4 个 head-actions:导出报价单 / 同步上游价格 / 切换到 JSON / + 新建模型价格)。
Phase C 已收口(2026-09-06,详见末尾「Phase C」段):同步上游价格引入 vvicat
PricingSourceAdapter抽象(newapi+local-seed双 adapter 注册)+ Source Selector UI(替换硬编码 upstreamUrl)+ Diff Preview Drawer(kind 分组展示 4 类分桶)+ Apply diff 端到端(写回prisma/model-prices.json+ 走 vvicat-pricing-seed-maintenance skill 保留管理员已编辑字段)。Phase B 真实 fetch 升级为「多 source 并发 + diff 预览 + Apply 二次确认」三步流程。Phase B 已收口(2026-09-06,详见末尾「Phase B」段):同步上游价格改为真实 fetch NewAPI
/api/pricing(前置弹窗收集 upstreamUrl/timeout);JSON 批量 Drawer 引入 zod schema 校验 + 错误明细展示;Drawer 实时预览卡新增「月度美元」列;后台数据集接入 NewAPI 仓库导出的 220+ LLM + 30+ 图像/视频真实价目作为参考基准(不写回 seed)。
用途
/admin/ai-pricing 集中管理平台对外销售模型调用消耗的「积分价格」,P1 阶段扩展为四个 Tab:
- 价格矩阵(主)——按模型 × 计量维度展示并编辑阶梯价。
- 未设置价格(P1 新增)—— 列出
billingMode = unpriced的 enabled 模型,一眼看到全平台漏配清单,每行一个「编辑」按钮复用既有 Drawer 流程。 - 价格模板库——把常用价格组合保存为可复用模板,发布时一键套用。
- 修订时间线——每次发布都生成一条修订记录,可回溯到任一历史版本。
主要场景:
- 调整单价:编辑矩阵行的「每单位积分」,Drawer 顶部实时预览卡(P1 新增)显示每个计费项的「倍率 / 最坏情况积分 / 最坏上游成本」,避免提交后才发现倍率错配。
- 发布价格:把矩阵变更固化为新修订版本,旧的 active 自动转为 archived。
- 应用模板:在矩阵行选「应用模板」按钮,选择模板并预览 diff,一键套用并发布新修订。
- 回滚定价:到「修订时间线」Tab 选择历史版本,点击「回滚」将其重新设为 active。
- 批量补价(P1 新增):到「未设置价格」Tab 一次性看完漏配模型,逐个点「编辑」补齐。
- 同步上游价格(P1 新增 / Phase B 真实 fetch):head-actions 点「同步上游价格」→ 弹 Modal 收集上游 Base URL(NewAPI
/api/pricingtype2 协议端点,如自部署http://127.0.0.1:3000)+ 超时(默认 10s)→ 真实 fetch NewAPI 上游 → 后端compareLocalToUpstream计算 differences → 返回{success, data: {differences, test_results, counts}}→ toast 显示「上游同步完成(N 已更新,M 跳过)」(N = 有 diff 的模型数;M = 本地已有但上游无 diff 的模型数)。详见 Phase B 段。 - JSON 批量编辑(P1 新增 / Phase B zod 校验):head-actions 点「切换到 JSON」打开 Drawer,粘贴整段
{ mediaType, tiers: [...], items: [...] }JSON → 「应用 JSON」先经 zodBulkPricingPayloadSchema校验(metric 白名单 / unitSize > 0 / bigint 字符串安全转换 / items 嵌套路径校验),校验失败时 antd Alert 展示完整 issues 列表(路径 + 错误描述 + 错误码),校验通过后调/api/admin/ai-pricing/bulk-json创建 DRAFT revision。
使用前准备
- 仅管理员账号可见;登录态与会话由 AdminGuard 守护。
- 价格矩阵的「模型」行键来自
/admin/ai-models中已启用的模型条目;调整前确认目标模型已在目录中。 - 重要:新建模型默认
enabled=false,价格矩阵与「未设置价格」Tab 均按enabled=true过滤。新建模型后请先到/admin/ai-models把该模型的「启用」开关打开,再到本页面(可通过/admin/ai-pricing?modelId={modelKey}深链接直达)为它设置价格,否则新建的模型在本页面任何 Tab 都看不到。 - 漏配巡检放宽:Round 3 起,「未设置价格」Tab 会同时列出
enabled=false且无 revision 的漏配模型(这些模型根本不参与生产计费,纳入 Tab 是为了帮 admin 看到「新建后忘了启用 + 漏配」清单)。summary接口的enabledModelCountKPI 仍只数enabled=true的模型,KPI 语义未变。 - 价格模板库支持
defaultTiers+defaultItems+applicableProtocols[]三段式定义;新建模板前准备好协议/维度组合。 - 默认换算比例为
1 USD = 1000 积分;管理员可逐行覆盖该比例的派生单价(积分仍以十进制整数保存)。 - 发布价格是高频操作,建议在低峰期执行并提前在测试环境验证模板与阶梯。
- P1 新增 metric 类型:
pricing-config.ts已扩展 7 种 metric(cache_read_tokens/cache_write_tokens/image_input/audio_input/audio_output/character_input+ 原有 8 种),LLM 模板出现cache_read_tokens阶梯表示按 prompt cache hit 计费;Image / Audio / TTS 模板出现*_input/*_output表示按输入/输出分别计费的多模态场景。
操作步骤
- 打开
/admin/ai-pricing。页面由AdminPricingPageClient承载,并发请求/api/admin/ai-pricing/matrix与/api/admin/ai-pricing/revisions填充矩阵与时间线;并实时拉取summary.models[]用于「未设置价格」Tab 的 badge 计数。 - 进入「价格矩阵」Tab;用供应商、媒体类型、状态、关键字筛选行(顶部筛选条)。
- 点击「编辑」打开价格编辑器(
pricing-editor/index.tsx)。Drawer 顶部实时预览卡(P1 新增 / Phase B 月度美元列)显示当前revision.tiers派生摘要:每个计费项的「单价 / 倍率 / 最坏情况积分 / 最坏上游成本 / 月度美元(1M tokens)」+ 合计行(合计月度美元 = 所有 metric 月度美元之和)。鼠标悬停倍率 / 最坏情况数字 / 月度美元 查看 Tooltip 公式说明(详见 FAQ)。 - 修改各 tier 的「每单位积分」或「上游微成本」→ 保存时(
POST /api/admin/ai-models/{modelId}/revisions)由后端validateRevisionPublish校验 LLM 强制要求(input_tokens+output_tokens都存在)。 - P1 漏配巡检:到「未设置价格」Tab,查看 badge 数字(未设置价格模型数;为 0 时显示「所有模型都已设置价格 ✓」);逐个点「编辑」补齐价格或调「同步上游价格」一键拉取。
- P1 JSON 批量 / Phase B zod 校验:head-actions 点「切换到 JSON」→ Drawer 打开带 5 items placeholder 的 textarea(覆盖 llm / image / audio / tts / video 各 1) → 粘贴 JSON → 「应用 JSON」先经 zod 校验 → 校验失败时 antd Alert 列出 issues(路径 + 描述) → 校验通过后调
/api/admin/ai-pricing/bulk-json创建 DRAFT revision(事务里累加 version + 写审计日志)。 - P1 同步上游 / Phase B 真实 fetch:head-actions 点「同步上游价格」→ 弹 Modal「上游 Base URL」+「超时(秒)」→ 确认 → 调
/api/admin/ai-pricing/sync-upstream(真实 fetch)→ 后端解析 NewAPI/api/pricingtype2 协议 → 计算 differences → 返回{success, data: {differences, test_results, counts: {upstream_models, local_models, diff_models}}}→ toast 显示「上游同步完成(N 已更新,M 跳过)」。 - 进入「修订时间线」Tab 查看历史变更(按
day-divider分隔的倒序时间线,含 up/down 类状态标签);必要时点击「回滚」将该版本重新设为 active。 - 进入「价格模板库」Tab 保存常用组合以便后续模型一键套价:「+ 新建模板」→ 填写
name / pricingType / defaultTiers / defaultItems / applicableProtocols[]→ 保存。
结果与状态
- 价格矩阵加载:每行展示「模型 + key · 媒体类型」、供应商、当前指标摘要、阶梯档数、每单位积分、状态徽标。
- P1 Drawer 实时预览卡 / Phase B 月度美元:在 Drawer 加载时 + 保存时点对点刷新(
pricing-editor/*是 inbox 保护的黑盒,不暴露 keystroke 级 state;后续若AdminPricingEditor暴露 onChange 回调可升级为实时联动)。数字「最坏情况积分 / 最坏上游成本」是按quantity = 1,000,000 × unitSize反推,月度美元(1M tokens) =worstCasePoints / 1000(1 USD = 1000 积分),格式:< $0.01/$0.05/$12.30/$100,000.00,详见 FAQ Q3 / Q4。 - 编辑单价:保存时仅更新当前模型的
DRAFT修订,未发布前对外仍按旧active计费。 - P1 未设置价格 Tab:badge 数字由
summary.models[].billingMode === 'unpriced'过滤后计数;为 0 时显示「所有模型都已设置价格 ✓」;每行「编辑」按钮复用既有openPriceRevisionDrawer走 Drawer 流程。 - Phase B 同步上游价格:调
/api/admin/ai-pricing/sync-upstream真实 fetch NewAPI/api/pricingtype2 协议(10s 默认超时 + 10MB body 上限 + http/https only 校验)→ 后端compareLocalToUpstream计算 differences(buildDifferences算法移植自 NewAPIcontroller/ratio_sync.go:536-696)→ 返回{differences, test_results, counts: {upstream_models, local_models, diff_models}}→ toast 显示「上游同步完成(N 已更新,M 跳过)」(N = diff_models 数量,M = local_models 中无差异数)。错误码:HTTP 400INVALID_PARAMS+details.reason(upstream-url-missing/upstream-url-invalid/upstream-timeout/invalid-upstream-status/invalid-upstream-body/upstream-network-error)。 - P1 JSON 批量 / Phase B zod 校验:Apply 成功后调矩阵刷新(沿用
handleSyncUpstream刷新策略),新 DRAFT revision 反映在矩阵的 status 列。校验失败时返回 HTTP 422 +details.issues: [{path, message, code}],Drawer 顶部 antd Alert 展示完整 issues 列表(路径 + 描述 + 错误码),不静默吞掉错误。 - 发布:新版本变为
ACTIVE(绿色 tag),旧ACTIVE转为ARCHIVED(灰色 tag),矩阵指针同步更新。 - 应用模板:diff 预览展示
defaultTiers与现有 tier 的差异;确认后写入新 DRAFT,需手动发布才生效。 - 回滚:选中历史版本点击「回滚」会生成一条新修订指向该版本的 tier 快照,旧
active仍转为archived。 - Tab 计数 badge:矩阵 Tab 显示当前筛选条件下的模型数;未设置价格 Tab 显示漏配模型数(badge 用警示色以提示补价);模板库 Tab 显示模板总数;时间线 Tab 显示历史修订条数。
权限和边界
- 仅管理员账号可见;登录态与会话由 AdminGuard 守护。
- 管理员可以覆写单价,但默认换算比例仍是初始化值,修改会持久化到模型目录,不会自动还原。
- 价格矩阵与
prisma/model-prices.json是双向同步:后台管理页变更后必须运行npm run export:model-prices固化配置。 - 价格修订一旦发布,历史
active自动转为archived,因此任何版本都可回滚但不可同时存在两份 active。 - 阶梯价的最小货币单位为「积分」,前端展示四舍五入;底层一律使用十进制整数保存以避免精度漂移。
- 删除模型前必须先在价格矩阵中清理与该模型相关的所有阶梯与修订,否则会出现孤儿定价行。
- 模板编辑采用「不可变覆盖」语义:PATCH 仅生成新版本,旧版本保留以便回溯。
- P1 JSON 批量 Drawer 仅做「形状 + 必填字段」校验,不做 schema 校验;具体业务规则(metric 白名单 / unitSize > 0 等)由后端
validateRevisionPublish兜底。Phase B 收口将引入 zod schema 校验。
常见问题
- Q:发布按钮点击后接口返回 422?
A:常见原因:当前 DRAFT 修订没有
protocol字段,或pricingDimensions与所选计费指标不匹配。打开编辑器补齐必填字段后重新提交。 - Q:模板库新建模板后列表不显示?
A:确认
pricingType与applicableProtocols[]至少有一个交集;过滤条件不匹配会被隐藏。可清空筛选条恢复。 - Q:回滚后价格矩阵没刷新?
A:回滚会生成新修订并切换指针;如果矩阵未刷新,刷新页面或重新进入 Tab 即可触发
GET /api/admin/ai-pricing/summary重新拉取。 - Q:单价改成了浮点数,保存报错? A:底层一律使用十进制整数保存;前端编辑框会自动把输入四舍五入到整数。如果手动粘贴带小数点的字符串,保存时会被服务端拒绝。
- Q:实时预览卡的「倍率」为什么显示 0.33×?看起来像打 3 折?
A:倍率 =
unitPoints × CURRENCY_MICROS_PER_USD × 10000 / (DEFAULT_POINTS_PER_USD × providerUnitCostMicros)。例如unitPoints=2+providerUnitCostMicros=3000000(= 3 USD) 时,倍率 =2 × 1000000 × 10000 / (1000 × 3000000)≈ 0.67(展示精度保留 2 位小数为 0.67×)。0.67× < 1 表示「按上游成本打 7 折卖」,是亏本定价;建议倍率 ≥ 1 才能保本。鼠标悬停倍率数字查看 Tooltip 完整说明。 - Q:实时预览卡的「最坏情况积分」按什么算?
A:
worst-case = quantity × unitPoints / unitSize 向上取整(token 类 metric)或ceil(quantity / unitSize) × unitPoints(其他 metric),其中quantity = 1,000,000 × unitSize。即「按单次最大用量估算」,不是历史峰值。鼠标悬停「最坏积分 / 最坏成本」查看 Tooltip 完整说明。 - Q:Phase B 新增的「月度美元」列是什么?
A:
月度美元(1M tokens)=worstCasePoints / 1000,因为1 USD = 1000 积分。即假设平台每月调用 1,000,000 tokens,最坏情况下积分消耗折合美元。格式:< $0.01(< 0.005 美元)/$0.05/$12.30/$100,000.00(千分位 + 2 位小数)。鼠标悬停数字查看「假设每月调用 1,000,000 tokens,最坏情况下积分消耗折合美元(1 USD = 1000 积分)」。合计行展示所有 metric 月度美元之和。 - Q:点「同步上游价格」后 toast 显示「已更新 N 跳过 M」,N 和 M 是什么?
A:Phase B 真实 fetch NewAPI
/api/pricingtype2 协议后,N = 后端compareLocalToUpstream计算的diff_models(本地与上游有差异的模型数),M =local_models - diff_models(本地有但与上游完全一致)。即 N 是实际改动条目数,不是演示值。如果上游返回非 200 / timeout / body 解析失败,会显示INVALID_PARAMS错误 toast + 详细details.reason。 - Q:「未设置价格」Tab 数字 badge 用警示色,是不是有 bug?
A:不是 bug。漏配价格会让生产计费挂空,所以 badge 用
--dramagon-state-warning橙色提醒管理员「该补价了」。数字为 0 时整段显示「所有模型都已设置价格 ✓」绿色成功态。 - Q:JSON 批量 Drawer 应用时报「JSON 校验失败(N 个错误)」,错误列表显示在哪里?
A:Drawer 顶部 antd Alert
type='error'红色横幅,下方表格列出每条 issue:路径(如items.3.unitPoints)+错误描述(如Expected bigint, received string)+错误码(zod issue code)。点击「修复后重新提交」修改 JSON 后再次点击「应用 JSON」即可。常见的错误:metric 不在白名单(仅 14 个 P1 metric 合法)/ unitSize ≤ 0 / bigint 字段传字符串但格式错 / 嵌套 tier 缺少必填字段。
相关文档
- AI 供应商管理 — 计费倍率与上游成本
- AI 模型目录 — 修订与活动版本切换
- 管理员后台(Dramagon 暗色主题) — 主题、通用组件、17 个子页面索引
- 模板管理 — 创作模板维护
- P1 价格体系深度设计意图与验收清单 —— 详见项目内
.learnings/ADR/2026-09-06-p1-pricing-depth.md(项目内知识库,不在公开文档路由) - Phase B 价格体系深度设计意图 —— 详见项目内
.learnings/ADR/2026-09-06-p1-pricing-phase-b.md(真实 NewAPI 上游 + zod schema + 月度美元换算;Phase A mock → Phase B 真实)
Phase B (2026-09-06)
在 P1 阶段(mock 同步 + 形状校验 + 简单预览卡)的基础上,Phase B 把价格中心从「演示可点」升级到「真实可用」,4 个升级:
1. 上游真实同步(FEAT-20260906-001 B2)
/api/admin/ai-pricing/sync-upstream 从 mock(仅返回 N 已更新)升级为真实 fetch NewAPI /api/pricing type2 协议:
- 请求:POST
{upstreamUrl, timeout?, apiKey?}(admin 弹 Modal 收集) - fetch:
GET ${upstreamUrl}/api/pricing(10s 超时 + 10MB body 上限) - 解析:type2
{success, data: Pricing[]}格式 - diff:移植 NewAPI
controller/ratio_sync.go:536-696的buildDifferences算法到src/lib/pricing/diff.ts - 响应:
{success, data: {differences, test_results, counts: {upstream_models, local_models, diff_models}}}
参考数据:src/lib/pricing/newapi-defaults.ts 收录 NewAPI 仓库导出的 220+ LLM modelRatio + 30+ image/video/audio/tts modelPrice + 5 audio + 7 audio completion + 4 completion + 1 image + 30 vendor rules + 26 vendor icons + completion 默认推导(基于前缀的智能 default;gpt-5-mini = {8, true} / claude-3-5-sonnet = {5, true} / gemini-2.5-pro = {8, false} 等)。
2. JSON 批量 zod schema 校验(FEAT-20260906-001 B3)
/api/admin/ai-pricing/bulk-json 从「形状 + 必填字段」升级为 zod schema 全量校验:
src/lib/pricing/json-schema.ts暴露BulkPricingPayloadSchema(zod object)+validateBulkPayloadhelper +flattenZodIssues- 14 个
PRICING_METRICSenum + 6 个MEDIA_TYPESenum + bigint 字符串安全转换(接受bigint/number.int/^\d+$字符串 →bigint) - 校验失败返回 HTTP 422 +
details.issues: [{path, message, code}] PricingBulkJsonDrawer.tsx顶部 antd Alert 展示完整 issues 列表,PLACEHOLDER 扩展为 5 items(input_tokens / output_tokens / image_input / audio_output / duration_seconds 覆盖 llm/image/audio/tts/video)
3. Drawer 实时预览月度美元列(FEAT-20260906-001 B4)
AdminPricingPreviewPanel.tsx 新增「月度美元(1M tokens)」列:
- 计算:
monthlyUsd = worstCasePoints / 1000(1 USD = 1000 积分) - 格式:
< $0.01/$0.05/$12.30/$100,000.00 src/lib/format/monthly-usd.ts提供formatMonthlyUsd(monthlyPoints: bigint | number | string): string纯函数(含 null/负数/0/非法串降级)- 合计行
totalMonthlyUsd = Σ monthlyUsd;底部 Typography hint 提示「假设每月调用 1,000,000 tokens,最坏情况下积分消耗折合美元」
4. 主代理集成(FEAT-20260906-001 B5)
新增 AdminSyncUpstreamDialog.tsx(113 行):
- antd Modal + Form,字段
upstreamUrl(type:‘url’ + prefixhttps?://)+timeout(InputNumber 1-60s) - AdminPricingPageClient 改造 handleSyncUpstream 签名
(params?: SyncUpstreamParams),无参时弹 Modal 收集参数,有参时真实 fetch - 头部按钮
onClick改为setSyncUpstreamDialogOpen(true)
scripts/verify-p1-phase-b.cjs 沙箱兜底验证脚本(228 行):16 文件 + 17 i18n key 中英对称 + BigInt 安全转换模式 + typecheck 仅看本次产物。
Phase B 验收
| 项 | 结果 |
|---|---|
| vitest | 205/205 PASS(4 文件:newapi-defaults 146 + json-schema 40 + sync-upstream 7 + preview-panel 12) |
| typecheck | 0 errors(本次产物;pre-existing 38 baseline 不阻断) |
| i18n | zh/en 各 244 keys 严格对称(Phase A 233 + Phase B 14 syncUpstreamDialog/bulkJson/pricingPreview + cancel) |
| inbox 保护 | pricing-editor/* 未触碰 |
| docs 同步 | content/{zh,en}/admin/ai-pricing.mdx 已更新描述 |
| inbox 设计稿 | Dramagon 设计稿未动(无视觉变化) |
Phase C (2026-09-06)
Phase B 把 sync-upstream 升级到「真实 NewAPI fetch + diff 计算」,但仍有 3 个绑定 NewAPI 的硬约束(接口层 / 算法层 / 协议名层)。Phase C 把硬约束全部抽到 vvicat 自己的 adapter 抽象后,新增 Source Selector UI + Diff Preview Drawer + Apply diff 端到端,把 sync-upstream 从「单源 fetch + diff 展示」升级为「多 source 并发 + diff 预览 + Apply 二次确认」三步流程。
1. vvicat PricingSourceAdapter 抽象(FEAT-20260906-001 C1)
sync-upstream/route.ts body 从 {upstreamUrl} 改为 {sources: [{type, params}]}:
pricingSources全局 registry 容纳所有PricingSourceAdapter(Phase C 已注册newapi+local-seed,详见src/lib/pricing/adapters/index.ts)defaultPresets:preset:local-seed(无参)+preset:newapi-public(baseUrl + timeout 默认值,开箱即用)applyPricingDiff()纯函数(src/lib/pricing/apply-pricing-diff.ts,vvicat-pricing-seed-maintenance skill 联动):kind=modified 字段白名单合并 / kind=added 追加 / kind=removed 标记deprecated: true(hardDelete=true 时真删,默认禁用)- vvicat 主语:不复用 NewAPI 协议名
type1/type2/type3/type4/pricingSyncFields/UpstreamDTO/convertOpenRouterToRatioData/ 官方预设 ID-100/-101;不复用ratio_setting.USD = 500换算常量(vvicat 用USD_TO_VVICAT_POINTS = 1000,AGENTS.md 强制)
2. diffSnapshots 算法(vvicat 类型化)
src/lib/pricing/diff-snapshots.ts(418 行):借鉴 NewAPI 4 类分桶(added / removed / modified / unchanged)但用 vvicat PricingMetric 联合类型做字段遍历;deltaPct 在 baselineValue=0 时返回 null(避免 UI 展示爆炸);默认 epsilon = 1e-6 浮点容差;排序:先按 kind 优先级,再按 modelKey 字典序。
3. Source Selector UI(替换硬编码 upstreamUrl)
src/app/[locale]/admin/components/pricing/source-selector.tsx(273 行):
- mount 时拉
/api/admin/ai-pricing/sources(client-safe DTO,剥除 fetch / healthCheck 函数) - antd Select dropdown 列出所有已注册 adapter(按注册顺序)
- 选完 type 后,根据该 adapter 的
paramSpecs动态渲染表单(text / number / password / select) - 受控 value + params 草稿,dialog 关闭时保留(destroyOnClose=false 可选)
4. Diff Preview Drawer + Apply diff 端到端
src/app/[locale]/admin/components/pricing/diff-preview-drawer.tsx(347 行):
- antd Drawer 按 kind 分组(added / removed / modified / unchanged)列出
entries[] - 每行展示 modelKey + kind Tag + changedMetrics 简要(metric + deltaAbs + deltaPct)
- 底部「应用差异」按钮触发
Modal.confirm显示applyDiffConfirm文案(管理员二次确认) - 用户确认后 POST
/api/admin/ai-pricing/apply-diff→ 成功后message.success(applyDiffSuccess)+ onApplied() 刷新矩阵 + 失败 message.error(applyDiffError)
接线:AdminPricingPageClient.tsx 改造 handleSyncUpstream 返回 Promise<SnapshotDiffResult> + 新增 handleApplyDiff(POST apply-diff + 刷新 matrix) + state 控制 DiffPreviewDrawer open。
5. vvicat-pricing-seed-maintenance skill 联动(scripts/apply-pricing-diff.ts 474 行)
- 不读取 / 覆盖 / 清除供应商密钥和管理员连接配置 → 脚本只读写
prisma/model-prices.json - 保留管理员已编辑字段(adminNotes / adminOverride / capabilities / maxUsage / costCurrency / pricingDimensions)
- 重复执行幂等:同 diff 跑两次结果一致(mergeEntry 检测无变更 → 计入
skipped) - kind=removed 默认标记 deprecated,不真删(hardDelete=true 时真删,路由层默认禁止)
Phase C 验收
| 项 | 结果 |
|---|---|
| typecheck | 0 errors on this commit’s outputs(worktree 全工程 tsc exit 0) |
| inbox 保护 | pricing-editor/* 0 line 改动(5 个 subagent 自检 + 主代理 git diff 验证) |
| 借鉴 vs 复制 grep | type1|type2|type3|type4|pricingSyncFields|UpstreamDTO|convertOpenRouterToRatioData|-100/-101|ratio_setting.USD 在 src/lib/pricing/ + 新 route + 新组件 0 命中 |
| i18n 对称 | pricingAdapters (8) + pricingPresets (4) + pricingDiff (6) + syncUpstreamPanel (7) = 25 keys 中英对称;累计 zh 269 / en 269 |
| vvicat-pricing-seed-maintenance skill 联动 | scripts/apply-pricing-diff.ts 实现不读取 / 覆盖 / 清除供应商密钥 + 保留管理员已编辑字段 + 重复执行幂等 |
| vitest 沙箱限制 | 沙箱 EPERM 拦截 spawn,无法在沙箱跑 vitest;测试文件结构正确,由用户 shell 复检兜底 |
Phase D backlog(未实施)
- FEAT-20260902-002:admin-api-timing 性能调优(独立 Round,4.5 天;admin 后台 API 响应时间压到 P95 < 500ms)
- OpenRouter adapter(
pricingSources.register(new OpenRouterAdapter()),如业务诉求触发,1.5 天) - models.dev adapter(
pricingSources.register(new ModelsDevAdapter()),如业务诉求触发,1 天) - canvas-node-admin-contract drift(价格 / 模型 / 供应商路由契约测试收口,独立 Round,0.5 天)