voc-cost-metering-and-balance-implementation-spec.md 107 KB

VOC 用量核算、成本预估与余额看板实现方案

文档状态:可进入技术评审 编写日期:2026-09-01 涉及仓库:claude-code-voc-intelligencefuture-serverfmode-studiovoc-profit-web

1. 背景与目标

当前企业用户已经能使用 VOC 技能完成批量社媒监听、电商商品采集和报告生成,但在成本侧存在四个直接影响交付的问题:

  1. 任务执行前,AI 不能回答“这项工作预计花多少钱”。
  2. 任务执行后,用户不能按报告、任务、模块和接口查看调用次数与消耗。
  3. 余额页只能看到总余额、已消费和充值信息,不能解释钱花在了哪里。
  4. 技能只知道接口参数,不知道可查询、可版本化的计费规则,无法主动做低成本方案比较。

本方案目标是形成一个统一闭环:

任务理解
  -> 生成采集计划
  -> 查询当前生效价目
  -> 返回低/中/高三档成本预估
  -> 检查余额与预算上限
  -> 携带任务追踪标识执行
  -> 余额不足时由 Agent 拼接现有 Balance 直达链接或取得现有支付二维码
  -> 现有充值链路完成支付和余额刷新,Agent 从本地检查点继续
  -> 记录每次实际扣费
  -> 缓存采集结果中的多媒体到本地任务目录
  -> 按任务/报告/模块/接口出账单
  -> AI 给出高成本低价值项的优化建议

本方案不在技能包、报告、日志或示例中保存账号密钥、会话令牌、API Key。历史敏感清单仅作为账户归属核对输入,不进入代码和 Git。

2. 用户要能直接得到的答案

2.1 执行前

用户用自然语言提问:

  • 监听 280 个小红书账号并生成日报,大概多少钱?
  • 拉取一个天猫店 134 个商品并生成 Listing 诊断,预计消耗多少?
  • 当前余额够不够?
  • 经济版、标准版、完整版分别采什么,价格和结果差异是什么?

AI 应返回:

  • 任务规模和计算假设。
  • 每个模块、接口的预计调用次数、单价和小计。
  • 大模型生成费用与 VOC 数据费用分开列示。
  • 低值、高值和预期值,而不是单一伪精确数字。
  • 当前余额、执行后预计余额、预算风险。
  • 可选的降本方案及其信息损失。

2.2 执行中

  • 达到用户预算的 80% 时提醒。
  • 达到硬预算上限时停止新增采集,保留已采数据并生成部分报告。
  • 余额不足时,Agent 计算差额和建议充值金额,直接拼接带 Token 的 Balance 链接。
  • Agent 根据交互环境返回免登录直达付费页,或直接返回支付二维码。
  • 现有 Balance 页面完成支付和余额刷新,Agent 查询新余额后使用原检查点继续执行。
  • 重试、缓存命中、失败调用的计费状态可解释。

2.3 执行后

  • 本任务总消费、VOC 数据消费、大模型消费。
  • 每个接口的调用次数、成功/失败/缓存次数、额度和人民币消耗。
  • 按报告、技能、步骤、账号或商品批次下钻。
  • 成本 Top 项及其业务贡献。
  • “删掉什么能省多少钱、会损失什么”的优化建议。
  • 报告引用的图片、视频和音频均来自本地任务目录,不依赖易失效的上游临时 URL,也不上传到线上 Storage。

3. 现有实现盘点(改造前基线)

本节记录方案启动时的缺口,便于对照改造范围;当前实现状态以第 18.1 节和第 21 节的验收记录为准。

3.1 VOC 技能包

相关文件:

  • skills/voc-api-catalog/SKILL.md
  • mcp/catalog/voc-social-endpoints.json
  • mcp/src/core/api-catalog.js
  • mcp/src/core/credentials.js
  • mcp/src/core/payment-links.js
  • mcp/src/core/activation.js
  • mcp/src/tools/voc-api-catalog-run.js
  • mcp/src/providers/voc-gateway.js
  • mcp/src/providers/ecommerce-gateway.js
  • mcp/src/providers/overseas-gateway.js
  • mcp/src/providers/xiaohongshu-api.js
  • mcp/src/providers/douyin-api.js
  • mcp/src/features/xiaohongshu-trend/live-collector.js
  • mcp/src/features/douyin-trend/live-collector.js
  • mcp/src/features/voc-business-workflow/business-workflow.js
  • mcp/src/features/fmode-image-analysis/image-analysis.js
  • mcp/src/server.js

已具备:

  • 接口目录、参数文档和三类网关路由。
  • NewAPI token 优先、会话 token 回退。
  • 401、402、403、参数错误和上游波动的区分。
  • 余额不足时返回充值入口。
  • 小规模 live 默认值和部分结果保留。

缺少:

  • 目录中的接口级计费字段和价目版本。
  • 任务执行前的调用计划与成本估算工具。
  • usageTraceId/reportId/skillId/stepId 等用量关联字段。
  • 每次调用实际扣费的结构化返回。
  • 整个报告工作流的预算上限和成本汇总。
  • 大模型用量与 VOC 数据调用的统一任务归集。
  • Agent 根据建议金额调用现有免登录 Balance/二维码能力,并在到账后继续的闭环。
  • 对所有采集多媒体统一执行本地缓存和报告 URL 替换的强制流程;本技能包不执行线上 Storage 上传。
  • 类型化区分 sk- NewAPI Token 与 r: Session Token,并让专用采集器和通用网关共享同一计费/充值上下文。

3.2 后端计费

相关文件:

  • fmode-server/modules/shared/newapi-metering.ts
  • fmode-server/modules/voc-social-api/src/routes.ts
  • fmode-server/modules/voc-e-commerce/src/routes.ts
  • fmode-server/modules/voc-ecom-api/src/routes.ts
  • api/api-ncloud/fmode/routes.js
  • api/api-ncloud/fmode/doc/migrate-apig-newapi-billing.js
  • api/api-ncloud/profit/service/revenue.service.js

已具备:

  • APIGNewApiBillingMap 保存模块级 model/service/billingMode/priceCny/quota
  • chargeNewApiUsage() 同步扣减用户和 token 额度,并写入 NewAPI logs
  • logs.other 已记录 billing_source/apig_id/price_cny/billing_mode/request_path/source/service
  • 计费前余额检查、402 余额不足和 requestId 幂等控制。
  • 经营看板已经能按模块、端点、用户聚合调用量、额度和金额。
  • 缓存命中与上游转发已经写入 source

关键缺口:

  1. APIGNewApiBillingMap 只到模块/模型级,无法表达每个 proxyPath 的单价、计费单位和生效版本。
  2. pathQuota 可以改变实际扣除额度,但日志中的 price_cny 仍来自模块级映射;现有看板在 per_call 模式下优先使用 price_cny,可能出现路径级扣额与展示金额不一致。
  3. logs 没有报告和任务关联字段,历史任务只能按用户和时间窗口猜测,不能形成可审计的单报告账单。
  4. 经营看板使用管理员看板密钥,不能直接作为普通账户余额页或 AI 的查询接口。
  5. 现有 /api/fmode/newapi/user 返回余额、充值和订阅,不返回模块、任务、接口用量。
  6. r: Session 分支仍扣减旧 APIGAuth.count,未进入 NewAPI 通用余额和日志,和本需求的新模式冲突。
  7. 三个 VOC 网关对业务成功、缓存和扣费时机的处理不完全一致,必须统一为同一条幂等计费流水线。
  8. 当前人民币与 quota 的换算依赖 NewAPI USDExchangeRate 和每单位 500,000 quota;路径 quota 与日志人民币金额没有共享同一个解析结果。

3.3 Fmode Studio 余额页

相关文件:

  • projects/fmode-studio/src/components/balance-modal.component.ts
  • projects/fmode-studio/src/modules/launcher/balance-page.component.ts
  • projects/fmode-studio/src/modules/launcher/auth-guard.service.ts
  • projects/fmode-studio/src/app/app.routes.ts
  • projects/fmode-studio/src/modules/launcher/fmode-home.component.ts

已具备:

  • 通过会话身份查询 Fmode API 余额、已用额度、充值和订阅。
  • 钱包充值、额度划转、套餐购买和支付二维码。
  • 支付状态轮询、支付成功提示和余额刷新。
  • Tokenized Balance 链接和 VOC 安装入口可以自动打开余额弹窗。
  • 独立 /balance 页面已经支持 ?token=,调用 Parse.User.become() 后立即从地址栏移除 Token。
  • 独立余额页已经按 /api/fmode/recharge/orderpay_code2order_status2 完成建单、二维码、轮询和到账刷新。

以上能力已在 fmode-studio 远端 origin/master97c64bcd5ae86fe9ade0bfuture-serveraf2541aa 中核实。本需求复用现有充值中心,不重做支付页面和订单逻辑。

缺少:

  • 日、周、月消费趋势。
  • 大模型、VOC 社媒、国内电商、海外电商等模块拆分。
  • 任务/报告账单和接口明细。
  • 计费规则页和 Agent 成本测算所需的数据查询。
  • 预算预警、余额可支撑任务量提示。
  • Agent 模型调用自身收到 402 后,由 Studio/Agent 运行时直接弹出充值入口的兜底;该动作不能依赖已经停止响应的模型继续调用工具。

3.4 原 VOC 经营看板

相关文件:

  • voc-profit-web/client/src/app/api.service.ts
  • voc-profit-web/client/src/app/dashboard.component.*
  • future-server/api/api-ncloud/profit/routes.js
  • future-server/api/api-ncloud/profit/service/revenue.service.js

可复用能力:

  • module-forwarding 的模块、端点、用户、最近调用聚合。
  • upstream-cost 的收入、上游成本、缓存率和利润分析。
  • 用户排行、时间趋势和充值流水。

复用原则:

  • 复用服务层的 SQL 口径和聚合思路。
  • 管理员经营视图继续留在 voc-profit-web
  • 面向个人/企业账户的新接口必须按当前身份限定 user_id,不能复用管理员全量返回。

4. 核心设计决策

4.1 三本账分开

账本 含义 面向对象
用户消费账 用户实际被扣除的额度与人民币金额 用户、AI、客服
上游成本账 平台向数据供应商和模型供应商支付的成本 运营、财务、产品
现金与充值账 用户充值、钱包划转、订阅购买 用户、财务

本期余额页重点展示用户消费账和现金充值账;上游成本与毛利继续留在管理员经营看板,避免把内部采购价暴露给普通用户。

4.2 计费规则只有一个权威来源

后端计费引擎是单价和实扣的权威来源。技能目录可以缓存公开价目快照,但不能自行维护另一套单价。Agent 通过接口读取当前价格后,按照自己生成的业务调用计划完成报价计算;服务端不替 Agent 决定报告方案和调用次数。

扣费、日志金额、余额页和 Agent 报价所读取的单价必须来自同一个规则解析函数:

resolveBillingRule(model, method, path, effectiveAt)
  -> billingMode
  -> unitName
  -> unitPriceCny
  -> quotaPerUnit
  -> pricingVersion
  -> cachePolicy

4.3 估算和实付严格区分

  • estimatedCostCny:执行前根据计划计算。
  • budgetLimitCny:Agent 执行时遵守的用户预算上限,不冻结、不预扣 NewAPI 余额。
  • actualCostCny:成功扣费日志汇总。
  • unpricedCostCny:缺少有效价目、只能按兜底规则估算的部分。

前端和 AI 不得把估算值显示为已消费。

4.4 任务追踪优先,不用时间窗口猜账

每次复杂报告执行由 Agent 本地生成 usageTraceId,每份输出可生成 reportId。所有 VOC 请求和可关联的大模型请求都携带同一 usageTraceId

usageTraceId 只是用量日志标签,用于精确拆分不同报告的接口频次和消费。它不是订单号,不创建独立余额,不冻结资金,也不改变扣费方式;所有调用仍然实时扣除同一用户的 NewAPI 通用余额。

历史任务没有这些字段时可以提供“按时间窗口推算”,但必须标记为 reconstructed,不能标记为精确账单。

4.5 Agent 调起现有充值中心,用户只完成支付

VOC 技能余额不足时,不让用户重新登录和寻找充值入口,由仍可运行的 Agent 完成充值前测算。默认优先返回二维码,自助链接作为另一种方式:

  1. 根据任务剩余计划计算差额和建议充值金额。
  2. 默认复用 /api/fmode/recharge/orderpay_code2,由 Agent 组装现有支付请求参数并直接返回支付二维码。
  3. 另一种方式是拼接 https://app.fmode.cn/dev/studio/balance/?token=USER_TOKEN,用户进入现有 Balance 页面自行选择金额。
  4. 支持网页跳转的客户端可以直接打开该链接;聊天或企微场景返回可点击链接。
  5. 现有 Balance 页面完成订单、支付轮询、到账划拨和余额刷新。
  6. Agent 再次查询余额,余额充足后从本地检查点继续未完成批次。

充值增加的是用户 NewAPI 通用余额,不是购买某个任务。充值订单不与 usageTraceId 做财务绑定;追踪标识只用于执行前后测算和实际账单归集。

4.6 两类余额不足必须分层处理

余额不足类型 发生位置 谁还能执行 正确处理
Agent 模型账户余额不足 大模型/NewAPI 模型调用返回 402 Agent 已经不能继续生成回复或调用技能 由 Studio、OpenClaw 或 Agent 宿主运行时拦截 402,直接展示现有 Balance 链接/充值卡片;同时在耗尽前做预警
VOC 技能数据余额不足 VOC 网关或 Skill 调用返回 needs_recharge Agent 模型仍可工作 Skill 强制计算剩余成本,默认组装支付请求返回二维码,也提供带 Token 的 Balance 链接

Skill 规则只能解决第二类。第一类不能设计成“让 Agent 再调用一个支付工具”,因为模型余额耗尽后这一步已经没有执行条件;必须由不依赖模型推理的宿主 UI/运行时完成兜底。

4.7 采集多媒体必须持久化

所有 VOC 采集结果中出现的图片、视频、音频及封面文件必须进入统一媒体流水线:

  1. 发现远程媒体 URL 后立即下载到本任务本地目录。
  2. 文件按内容摘要命名并去重,写入 outputs/<usageTraceId>/assets/
  3. 标准化数据和报告中的展示 URL 一律使用本地相对路径。
  4. 原始平台 URL 只保留在媒体清单的 sourceUrl 中用于溯源,不作为报告主要展示地址。
  5. 下载失败必须记录状态并明确降级,不得悄悄继续引用易失效的远程链接。
  6. 本技能包不读取 Storage 凭证、不申请预签名 URL、不调用线上上传接口。

5. 统一数据模型

5.1 路径级价目表 APIGEndpointPricing

不建议继续把大量路径规则塞进运行时 pathQuota 配置。新增可查询、可版本化的数据表:

字段 类型 说明
objectId string 主键
model string voc-social / voc-e-commerce / voc-ecom
channel string social / ecommerce / overseas
endpointId string 技能清单中的稳定 ID
method string HTTP 方法
proxyPath string 规范化路径,不含 query
billingMode string per_call / per_page / per_item / per_minute / per_token
unitName string 次、页、商品、账号、分钟、千 token 等
unitPriceCny number 对用户展示的单位价格
quotaPerUnit integer 实际扣除额度
cachePolicy string same_as_upstream / discounted / free
cacheQuotaPerUnit integer/null 缓存命中的扣额
pricingVersion string 2026-09-01.1
effectiveFrom date 生效时间
effectiveTo date/null 失效时间
enabled boolean 是否启用
source string 价格来源和校准方式
metadata object 标题、说明、限制等非敏感信息

匹配优先级:

  1. model + method + proxyPath 精确匹配。
  2. model + endpointId 匹配。
  3. 回退 APIGNewApiBillingMap 模块级规则。
  4. 缺少任何有效规则时,预估接口返回 unpriced;生产扣费是否允许兜底由服务配置决定。

5.2 用量追踪上下文 UsageTrace

字段 类型 说明
usageTraceId UUID Agent 本地生成的一次报告执行标识,不是支付或扣款 ID
clientId string/null 安装实例或 Agent 标识,自报标签
skillId string voc-api-catalog
workflowType string xhs_account_monitortmall_listing_audit
title string 用户可读任务名
reportId string/null 报告或输出标识
stepId string/null 当前采集步骤
budgetLimitCny number/null Agent 本地预算上限,不冻结余额
estimateLowCny number 低值
estimateExpectedCny number 预期值
estimateHighCny number 高值
pricingVersion string 预估时价目版本
plan object Agent 本地保存的结构化调用计划,不含密钥

首期不要求服务端新增 UsageTask 表或任务 CRUD API。追踪上下文写入本地检查点和 NewAPI logs.other 即可;当前用户用量接口按 usageTraceId 聚合实际日志。

5.3 报告本地元数据 UsageReport

字段 类型 说明
reportId UUID 报告 ID
usageTraceId UUID 所属执行追踪标识
reportType string 日报、排行、Listing 诊断等
title string 报告名称
artifactUrl string/null 交付地址,可选
scope object 账号数、商品数、日期等
status string partial/completed/failed

5.4 充值数据沿用现有账务模型

不新增与报告绑定的 BillingPaymentSession。充值继续使用现有支付订单、钱包账本、NewAPI top_ups 和余额刷新逻辑。Agent 只提供建议金额和访问方式,不建立一次性任务支付关系。

5.5 媒体清单 media-manifest.json

每次报告执行生成 outputs/<usageTraceId>/assets/media-manifest.json

{
  "usageTraceId": "USAGE_TRACE_ID",
  "items": [
    {
      "mediaId": "MEDIA_ID",
      "entityType": "note",
      "entityId": "ENTITY_ID",
      "mediaType": "image",
      "sourceUrl": "SOURCE_URL",
      "localPath": "outputs/USAGE_TRACE_ID/assets/xiaohongshu/ENTITY_ID/HASH.jpg",
      "cloudUrl": null,
      "effectiveUrl": "outputs/USAGE_TRACE_ID/assets/xiaohongshu/ENTITY_ID/HASH.jpg",
      "mimeType": "image/jpeg",
      "bytes": 123456,
      "sha256": "HASH",
      "cacheStatus": "cached",
      "uploadStatus": "disabled_local_only"
    }
  ]
}

effectiveUrl 固定取 localPathcloudUrl 固定为 nulluploadStatus 固定为 disabled_local_only。报告生成器只能消费 effectiveUrl

5.6 NewAPI logs.other 扩展字段

继续使用现有 logs 作为实际扣费事实表,在 other 中增加:

{
  "billing_source": "apig",
  "service": "voc-social-api",
  "request_path": "TARGET_PATH",
  "request_method": "GET",
  "source": "upstream",
  "endpoint_id": "xiaohongshu.get_user_note_list_v4",
  "usage_trace_id": "USAGE_TRACE_ID",
  "report_id": "REPORT_ID",
  "skill_id": "voc-api-catalog",
  "workflow_type": "xhs_account_monitor",
  "step_id": "collect_account_notes",
  "client_id": "CLIENT_ID",
  "billing_mode": "per_call",
  "unit_name": "call",
  "unit_count": 1,
  "unit_price_cny": 0.1,
  "actual_cost_cny": 0.1,
  "pricing_version": "2026-09-01.1",
  "cache_policy": "same_as_upstream"
}

约束:

  • actual_cost_cny 必须由本次实际扣除 quota 和已解析规则生成,不再从模块级 price_cny 反推。
  • 用户传入的追踪字段必须限制长度和字符集。
  • userId/tokenId 只能从鉴权结果得到,不能接受客户端覆盖。
  • clientId 是展示维度,不作为强权限边界;同一账户共享同一密钥时,Agent 归属只能视为自报标签。

6. 后端 API 契约

统一前缀建议使用 /api/fmode/billing。同时支持两种身份:

  • Studio:请求体或 Cookie 中的会话身份。
  • Claude Code/MCP:Authorization: Bearer <NewAPI key>

所有返回只包含当前账户数据。

接口数量边界:计费、报价数据准备和用户用量只新增下面一个 billing/query 聚合接口,通过 include 和筛选入参一次返回 Agent 当前所需数据;Agent 在本地生成计划并计算报价。充值复用现有 3 个调用,不新增支付接口。媒体本轮只落本地,不调用 Storage 接口。

6.1 当前用户计费统一查询

新增一个聚合接口,同时服务 Agent 报价和 Balance 页面:

POST /api/fmode/billing/query
Authorization: Bearer USER_TOKEN
Content-Type: application/json

Agent 执行前只查询余额和候选接口价格:

{
  "include": ["balance", "pricing"],
  "pricingFilter": {
    "channels": ["social"],
    "endpointIds": [
      "xiaohongshu.search_user_v2",
      "xiaohongshu.get_user_note_list_v4",
      "xiaohongshu.get_note_comments_v3"
    ]
  }
}

以上是 Agent/MCP 内部结构,不是要求用户填写的表单。用户继续用自然语言描述任务,Agent 负责抽取范围、补默认值并生成候选调用计划。

Balance 页面查询当前用户用量:

{
  "include": ["balance", "pricing", "usage"],
  "pricingFilter": {
    "channels": ["social", "ecommerce", "overseas"]
  },
  "usageFilter": {
    "from": "2026-08-30",
    "to": "2026-09-01",
    "usageTraceId": "USAGE_TRACE_ID",
    "groupBy": ["module", "endpoint", "usageTraceId"],
    "page": 1,
    "pageSize": 100
  }
}

统一响应:

{
  "code": 200,
  "data": {
    "balance": {
      "availableCny": 30,
      "usedCny": 120
    },
    "pricing": {
      "version": "2026-09-01.1",
      "currency": "CNY",
      "items": [
        {
          "endpointId": "xiaohongshu.get_user_note_list_v4",
          "channel": "social",
          "method": "GET",
          "proxyPath": "TARGET_PATH",
          "billingMode": "per_call",
          "unitName": "次",
          "unitPriceCny": 0.1,
          "quotaPerUnit": 7353,
          "cachePolicy": "same_as_upstream"
        }
      ]
    },
    "usage": {
      "totals": {
        "calls": 280,
        "billedCalls": 280,
        "quota": 2058840,
        "costCny": 28
      },
      "groups": [],
      "quality": "exact"
    }
  }
}

接口约束:

  • 服务端只返回当前用户的余额、筛选后的有效价目和实际用量,不生成最终报价。
  • Agent 根据业务范围自行生成调用计划,并计算低值、预期值和高值。
  • includegroupBy、时间范围、接口数量和分页大小均使用服务端白名单和上限。
  • 用量查询始终强制附加当前 user_idusageTraceId 只是附加筛选条件。
  • quality=exact 表示日志有追踪标识和实际金额;历史数据继续标记 mixed/reconstructed

6.2 Agent 调起现有充值能力

充值中心已有余额展示、金额选择、二维码、支付轮询和到账刷新能力,本需求不重新实现这套支付链路。提供两种方式:

方式一,用户自助选择金额:

https://app.fmode.cn/dev/studio/balance/?token=USER_TOKEN

独立 Balance 页已经消费 token 完成免登录识别,并在识别后从地址栏移除。用户进入页面后自行选择充值金额。

方式二,默认由 Agent 直接返回支付二维码:

POST /api/fmode/recharge/order
POST /parse/functions/pay_code2
POST /parse/functions/order_status2

Agent 根据建议充值金额生成 tradeNo,调用现有 recharge/order 创建或复用 AccountLog,再调用 pay_code2 取得 code_url 并渲染二维码。需要等待到账时复用 order_status2;这三步均为现有链路,不新增 billing 支付接口。

统一交互规则:

  • 默认优先由 Agent 返回二维码,减少用户再次选择和操作。
  • 用户希望自行选择金额,或当前环境不适合展示二维码时,返回带 Token 的 Balance 链接。
  • 支持打开浏览器的 Agent 可以直接打开该链接;其他聊天环境返回可点击链接。
  • 页面继续使用现有支付二维码、支付按钮、订单查询和余额刷新逻辑。
  • 充值金额进入用户 NewAPI 通用余额,与 usageTraceId、报告和单次任务不做财务绑定。
  • 到账后 Agent 再调用 /api/fmode/billing/query 查询最新余额,并从本地检查点继续。

6.3 本地媒体持久化

本轮明确采用本地优先且线上禁用的策略,不新增或调用 Storage 上传接口。媒体处理流程如下:

  1. 技能从采集响应中发现图片、视频、音频和封面 URL。
  2. 立即下载到 outputs/<usageTraceId>/assets/<platform>/<entityId>/,按 SHA-256 去重。
  3. media-manifest.json 记录 sourceUrllocalPath、摘要、MIME、大小和缓存状态。
  4. 报告与标准化数据的 effectiveUrl 一律使用本地相对路径。
  5. cloudUrl 固定为 nulluploadStatus 固定为 disabled_local_only
  6. 不请求 storage/profile、预签名 URL 或上传完成接口,避免消耗线上 Storage 资源。

7. 计费引擎改造

7.1 newapi-metering.ts

把当前 resolveQuota() 升级为 resolveBillingRule(),返回完整规则:

type ResolvedBillingRule = {
  quota: number;
  billingMode: string;
  unitName: string;
  unitCount: number;
  unitPriceCny: number;
  actualCostCny: number;
  pricingVersion: string;
  cachePolicy: string;
  matchedBy: "endpoint" | "module" | "fallback";
};

chargeNewApiUsage() 返回值增加:

{
  quota,
  costCny,
  pricingVersion,
  userId,
  tokenId,
  channelId,
  logId
}

并将解析后的真实金额写入日志。这样余额页不再依赖可能失真的模块级 price_cny

7.2 三个 VOC 网关模块

voc-social-apivoc-e-commercevoc-ecom-api 做同样改造:

  1. 从白名单请求头读取任务上下文。
  2. 规范化 proxyPath 并映射 endpointId
  3. assertNewApiQuotaAvailable()chargeNewApiUsage() 使用同一条已解析规则。
  4. 成功响应增加非敏感计费头:

    X-Fmode-Usage-Quota: 7353
    X-Fmode-Usage-Cny: 0.100000
    X-Fmode-Pricing-Version: 2026-09-01.1
    X-Fmode-Usage-Source: upstream
    
  5. JSON 响应暂不强制改变,避免破坏旧客户端;MCP 从响应头读取实际用量。

7.3 幂等与重试

  • 技能为每个逻辑调用生成稳定 requestId
  • 同一 requestId + model + fingerprint 只扣一次。
  • 同一 requestId 参数变化继续返回 409,防止错误复用。
  • 5xx 重试沿用同一 requestId
  • 业务失败不扣费;成功的缓存命中按 cachePolicy 扣费。
  • 用量统计分别展示尝试次数和计费次数,避免把网络重试误认为多次收费。

8. 技能包改造

8.1 新增核心模块

mcp/src/core/billing-client.js
mcp/src/core/usage-context.js
mcp/src/core/budget-guard.js
mcp/src/core/recharge-client.js
mcp/src/features/voc-cost/workflow-planner.js
mcp/src/features/voc-cost/estimate-report.js
mcp/src/features/media/media-pipeline.js
mcp/src/features/media/media-manifest.js
mcp/src/tools/voc-cost-estimate-run.js
mcp/src/tools/voc-usage-report-run.js
skills/voc-cost-controller/SKILL.md
skills/voc-cost-controller/references/workflow-cost-models.md

职责:

  • billing-client.js:按筛选条件调用统一 /api/fmode/billing/query,读取余额、价目和实际用量。
  • usage-context.js:本地创建和传递 usageTraceId/reportId/stepId,不创建服务端任务或支付记录。
  • budget-guard.js:Agent 根据当前余额、本地预算和实际用量,在执行前及批次间做检查。
  • recharge-client.js:计算差额后默认复用现有建单和 pay_code2 返回二维码;同时提供带 Token 的 Balance 自助链接。
  • workflow-planner.js:把自然语言任务转换成确定性的接口调用计划。
  • estimate-report.js:生成用户可读的三档报价和降本说明。
  • media-pipeline.js:发现、下载、去重、校验、写入本地并替换多媒体 URL。
  • media-manifest.js:维护媒体原地址、本地地址和处理状态,不保存线上访问地址。

8.2 新增 MCP 工具

voc_cost_estimate

输入保持业务化:

{
  "task": "监听 280 个小红书账号并生成门店排行榜",
  "workflowType": "xhs_account_monitor",
  "accountCount": 280,
  "unresolvedAccountCount": 105,
  "notesPerAccount": 5,
  "commentPagesPerNote": 0,
  "mode": "standard",
  "budgetCny": 100
}

voc_usage_report

输入 usageTraceId/reportId 或日期范围,通过同一个 billing query 接口取得实际用量,返回可直接发送给用户的成本报告。

首期只新增以上两个用户可见 MCP 工具。voc_cost_estimate 内部完成业务计划生成、价目查询、报价和余额比较;预算检查和充值入口作为工作流内部 helper,不再拆成多组 MCP 工具。

8.3 扩展现有工具输出

voc_api_call 及专用采集工具的标准结果增加:

{
  "usage": {
    "usageTraceId": "USAGE_TRACE_ID",
    "reportId": "REPORT_ID",
    "endpointId": "ENDPOINT_ID",
    "calls": 1,
    "billedCalls": 1,
    "quota": 7353,
    "costCny": 0.1,
    "pricingVersion": "2026-09-01.1"
  }
}

整个工作流结束时,summary 增加:

{
  "estimatedCostCny": 42.8,
  "actualCostCny": 40.6,
  "remainingBalanceCny": 59.4,
  "usageReportUrl": "URL"
}

8.4 技能行为规则

复杂任务满足任一条件时必须先估算:

  • 账号数、商品数或关键词数大于 20。
  • 预计接口调用超过 50 次。
  • 用户明确询问成本、余额或性价比。
  • 定时任务首次创建或采集范围显著扩大。

默认策略:

  • 首轮先给经济版、标准版、完整版。
  • 默认执行标准版,但预计费用超过可配置阈值时等待用户确认。
  • 有明确 budgetCny 时把它作为硬上限。
  • VOC 数据余额不足时先保存检查点,再由 Agent 计算差额;默认组装现有支付请求返回二维码,同时提供带 Token 的 Balance 自助链接。
  • Agent 模型余额不足不进入 Skill 流程,由 Studio/OpenClaw/Agent 宿主运行时拦截模型 402 并直接显示充值入口。
  • 现有 Balance 页面完成支付和余额刷新;当前 Agent 会话继续查询余额并从检查点恢复,不要求用户重新发起采集。
  • 如果用户暂不支付,再提供缩小范围或基于已有结果出部分报告的选项。
  • 报告必须附成本摘要,不附密钥和原始鉴权错误。

8.5 多媒体强制处理规则

所有 VOC 采集工具和报告工作流必须遵守:

  1. 递归识别响应中的图片、视频、音频、封面、买家秀和详情长图 URL。
  2. 在继续下一采集批次前,把新发现的媒体写入 media-manifest.json
  3. 下载到 outputs/<usageTraceId>/assets/<platform>/<entityId>/,以内容摘要命名并去重。
  4. 校验 HTTP 状态、实际 MIME、文件大小和 SHA-256;不信任仅由扩展名声明的类型。
  5. 标准化 JSON 保留 sourceUrl/localPath/cloudUrl/effectiveUrl,其中 cloudUrl 固定为 nulleffectiveUrl=localPath
  6. 报告只能引用 effectiveUrl,保证离线浏览且不产生线上 Storage 流量。
  7. 带时效签名的上游地址优先下载,不能延迟到报告生成阶段。
  8. 单文件失败自动重试;最终失败时记录原因并在报告中显示“媒体缓存失败”,不回退为远程热链。
  9. 任务结束前执行媒体完整性检查;存在未处理媒体时任务状态为 partial,不得声称完整交付。

现有 cacheEvidenceAssets() 可以作为图片下载的第一版基础,但需要扩展到视频、音频、详情长图、去重、断点续传和 URL 重写;线上 Storage 上传不在本轮范围内。

9. 通用成本模型与首批报告样例

成本能力必须对所有 VOC Skill、任意报告和任意复杂采集任务通用,不限定小红书和天猫。通用过程是“Skill 生成步骤和计费单位计划 → billing query 按 endpoint 筛选返回价目 → Agent 计算三档报价 → 实际调用按 usageTraceId 归集”。

下面两类报告只是首批可回放、可验收的基准样例,用于验证通用模型,不是功能范围边界。后续其他平台和工作流只需提供步骤规划适配器,不新增另一套计费接口。单价必须运行时从后端读取,文档中的 P(endpoint) 表示该接口当前生效单价。

9.1 小红书账号监听与门店排行

输入变量:

变量 含义
A 登记账号数,本场景为 280
D 已有直链、可直接取用户 ID 的账号数,本场景为 179
S 需要搜索匹配的账号数,本场景为 105;与 A-D 的差异必须作为数据质量提示
C 本轮实际覆盖账号数,已知历史执行在 147 个时停止
N 每账号读取的笔记页数
K 每条入选笔记读取的评论页数
R 每账号进入详情/评论的笔记数

基础调用公式:

账号解析费用
= S * P(xiaohongshu.search_user_v2)

账号笔记费用
= A * N * P(xiaohongshu.get_user_note_list_v4)

笔记详情费用(按需)
= A * R * P(xiaohongshu.get_note_detail_vN)

评论费用(按需)
= A * R * K * P(xiaohongshu.get_note_comment_vN)

报告生成费用
= LLM(inputTokens, outputTokens, cacheTokens, modelPrice)

三档建议:

模式 采集策略 适用场景
经济版 只搜索未解析账号;每账号 1 页笔记;不逐条拉评论;用已有互动字段排行 日报、赛事榜单
标准版 每账号 1 页笔记;只对 Top/新增笔记拉详情;仅异常样本拉评论 周报、运营诊断
完整版 多页笔记;入选笔记全量详情和评论;补用户画像 月报、深度研究

历史报告回算说明:

  • 当前日志没有 usageTraceId/reportId,无法把同一账户同一时段的其他调用排除。
  • 第一版只能用报告运行起止时间、用户 ID、模型名和路径做 reconstructed 回算。
  • 新版上线后,同一报告执行使用同一 usageTraceId,即可精确回答覆盖 147 个账号前花了多少、剩余 133 个还需多少。

9.2 天猫店铺商品 Listing 诊断

输入变量:

变量 含义
G 店铺商品列表页数,本场景已知为 5
A 店铺在售商品数,本场景为 134
S 进入完整诊断的代表商品数,已交付报告为 8
K 每商品评论页数
V 每商品调用的详情版本数

推荐调用公式:

店铺商品清单
= G * P(taobao.get_shop_item_list_v4)

全店轻量字段
= A * P(最小可用详情接口)

代表商品价格/SKU/主图
= S * P(taobao.get_item_detail_v4)

代表商品销量/长图/视频/属性
= S * P(taobao.get_item_detail_v3)

代表商品评价
= S * K * P(taobao.get_item_comment_v3)

报告生成
= LLM(inputTokens, outputTokens, imageTokens, modelPrice)

三档建议:

模式 采集策略 价值与成本
经济版 5 页店铺清单 + 按销量/新品/价格分层抽 8 个代表 SKU 最适合快速体检,避免 134 个商品全部深采
标准版 134 个商品拉轻量字段,Top 20 做完整详情与评论 能兼顾全店覆盖和诊断深度
完整版 134 个商品全部拉价格、详情、素材、评价并逐页打分 成本最高,仅在需要逐 SKU 改版清单时使用

接口选择规则:

  • 不为“保险”并发调用多个详情版本。
  • 先使用当前技能文档确认的可用版本;只有字段缺失时才调用补充版本。
  • 已知不稳定或不支持的版本不进入默认计划。
  • 失败且未计费的探测也要计入“尝试次数”,但不能计入“实际消费”。
  • 详情长图和评论只有在评分模型实际使用时才采集。

9.3 成本价值判断

每个步骤增加下列业务字段:

{
  "required": true,
  "valueScore": 5,
  "valueLabel": "门店排行核心字段",
  "omissionImpact": "不再能计算账号活跃率",
  "fallback": "使用上次快照"
}

成本报告按以下指标排序:

costShare = stepCost / taskCost
valuePerCny = valueScore / stepCost
wasteCandidate = !required && costShare >= 0.1 && valueScore <= 2

valueScore 是业务配置和人工校准结果,不应由接口价格自动推断。AI 可以提出建议,但删除采集项前必须说明信息损失。

10. 大模型用量归集

VOC 数据费和报告生成的大模型费必须分开显示。

10.1 P0

  • 精确统计有追踪标识的 VOC API 调用。
  • 大模型用量按同一用户、任务起止时间给出 reconstructed 估算。
  • 无法关联的模型调用列为“未归集”,不强行塞入某份报告。

10.2 P1

  • Agent/Claude 运行时创建统一 usageTraceId
  • MCP 请求和模型网关请求都传递该 usageTraceId
  • AIGate 写入模型调用的输入、输出、缓存 token、金额和任务上下文。
  • 用量查询将 billing_source=apig 与模型日志按 usageTraceId 合并。

最终任务账单:

{
  "dataCollectionCny": 36.4,
  "modelGenerationCny": 8.2,
  "otherModuleCny": 0,
  "totalCny": 44.6
}

11. Balance 页面信息架构

在现有余额弹窗基础上补充用户成本测算和用量展示。充值中心已有 Token 免登录识别、余额展示、金额选择、支付二维码/按钮、支付轮询和到账刷新,本需求复用并回归验证,不另建支付中心。

建议整理为四个页签:

  1. 总览:可用余额、今日/近 7 日/本月消费、预计可支撑任务量、预算预警。
  2. 用量:模块占比、每日趋势、任务/报告列表、接口消耗排行。
  3. 计费规则:每个模块和接口的计费单位、当前单价、生效时间、缓存规则。
  4. 充值与套餐:保持现有钱包、二维码、划转、订阅、Token 免登录和到账刷新逻辑;自助链接内由用户选择金额,Agent 直出二维码时使用建议金额。

11.1 总览

展示:

  • Fmode API 当前余额。
  • 本月已消费及环比。
  • 大模型 / VOC 社媒 / 国内电商 / 海外电商 / 其他模块。
  • 最近 5 个报告执行记录及状态。
  • “按最近 7 天速度预计可用 N 天”。
  • 有待执行任务时显示“完成该任务预计还需 ¥X”。
  • 从 Agent 返回的 Token 链接进入时不显示登录步骤和无关设置,用户直接选择金额并支付;Agent 默认二维码模式则在聊天中直接展示按建议金额创建的支付码。
  • 支付成功后沿用现有余额刷新;当前 Agent 会话重新查询余额并从本地检查点继续。

11.2 用量

筛选:

  • 今日、7 天、30 天、自然月、自定义。
  • 模块、技能、任务、报告、接口。
  • 计费来源、缓存/上游、成功/失败。

明细字段:

  • 时间、任务、报告、模块、接口、步骤。
  • 调用次数、计费次数、缓存次数。
  • 单价、额度、人民币金额、价目版本。
  • 数据质量 exact/mixed/reconstructed

支持 CSV 导出,但导出中不包含 token、请求体、原始评论或商品数据。

11.3 成本优化视图

默认展示 Pareto 排行:

  • 消耗最高的前 10 个接口。
  • 占总费用比例。
  • 对应报告指标。
  • 可关闭/降采样的建议。
  • 预计节省金额与影响范围。

例如:

逐条评论采集占本任务 43%,但门店排行榜只使用发帖数和互动总量。
切换为“只采 Top 20 账号评论”预计节省 ¥X,门店排行不受影响,评论洞察覆盖率下降。

12. 管理员经营看板改造

voc-profit-web 保留经营角色,并增加:

  • 价目版本和未定价接口告警。
  • 实扣额度与展示人民币金额一致性校验。
  • usageTraceId/workflowType/skillId 聚合。
  • 企业账户、token、安装实例的消费拆分。
  • 失败率、缓存率、单位有效样本成本。
  • 用户收入、上游采购成本和毛利继续分列。

现有 module-forwarding 可作为实现底稿,但需要:

  1. 使用 actual_cost_cny 替代旧 LOG_CNY_SQL 的模块价回退。
  2. 新增当前用户版本的聚合函数,强制 WHERE user_id = $currentUserId
  3. 增加执行追踪、报告、步骤分组。
  4. 对历史记录保留兼容计算并标记 mixed

管理员任务级诊断已落地为现有经营看板的一条管理员路由:

GET /api/profit/api/usage-diagnostics?days=2&limit=200

可选筛选参数为 usageTraceIdreportIdworkflowType。返回内容包括任务汇总、接口调用频次、计费 quota、实际消费、缓存命中、上游调用以及高成本低价值候选和预计节省金额。该路由继续使用看板管理员鉴权,不向普通 Balance 用户开放;用户侧仍只调用 POST /api/fmode/billing/query

13. 分仓开发清单

13.1 future-server

P0:

  • 新增 APIGEndpointPricing 表和迁移/seed。
  • 抽取统一 resolveBillingRule()
  • 修正路径级扣额与日志金额不一致。
  • 扩展 logs.other 追踪和实际金额字段。
  • 增加统一 /api/fmode/billing/query,通过入参筛选返回当前用户余额、价目和用量。
  • 复用现有 /api/fmode/recharge/orderpay_code2order_status2,不新增 billing 支付接口。
  • 不接入个人 Storage 探测、预签名上传和完成确认 API;媒体仅写入本地。
  • 增加当前账户鉴权和数据隔离测试。
  • 三个 VOC 网关返回用量响应头。

P1:

  • 大模型调用接入统一 usageTraceId
  • 增加企业/Agent 展示维度。
  • 支付成功事件主动唤醒任务运行时,减少 Agent 轮询。

13.2 claude-code-voc-intelligence

P0:

  • 新增 voc-cost-controller skill。
  • 新增计费客户端、任务上下文和预算守卫。
  • 新增充值客户端和本地媒体流水线;默认二维码、自助链接作为第二入口。
  • 注册 voc_cost_estimatevoc_usage_report 两个 MCP 工具。
  • voc_api_call 传追踪头并读取实际用量头。
  • 小红书/抖音专用 collector 使用同一网关和用量上下文。
  • 所有会发起计费采集的现有 Skill 引用同一工作流计划、价目查询、追踪、预算守卫和 VOC 402 处理规则。
  • 所有采集结果递归识别多媒体并写入本地媒体清单。
  • 报告展示 URL 固定替换为本地缓存路径,不上传线上 Storage。
  • 建立通用成本规划协议,并以小红书和天猫两个场景作为首批确定性模板。
  • 报告输出增加成本摘要。

P1:

  • 基于历史实际值校准预估区间。
  • 自动生成成本优化建议。
  • 后续新增 Skill 强制接入通用协议,新平台只提供步骤规划适配器。

13.3 fmode-studio

P0:

  • 保留现有充值和订阅逻辑。
  • 新增总览、用量、计费规则页签。
  • 接入统一 billing query 接口。
  • 支持执行追踪/报告下钻和 CSV 导出。
  • 余额不足提示显示缺口与建议充值金额。
  • 验证并保持现有 Token 免登录、二维码、支付按钮和到账刷新能力。
  • Agent 模型调用 402 时由 Studio/宿主运行时直接显示现有充值入口,不依赖模型继续执行。

P1:

  • 展示 Agent 三档报价记录与最终实付偏差。
  • 预算阈值设置和通知。

13.4 voc-profit-web

  • 复用新的统一聚合服务。
  • 增加价目一致性、未定价和未归集告警。
  • 增加任务、工作流和企业维度。
  • 保留上游成本、利润等管理员专属字段。

14. 实施顺序

阶段 A:先把账记准

  1. 建路径级价目表。
  2. 统一规则解析。
  3. 日志写实际金额和价目版本。
  4. 三个 VOC 模块接入任务追踪头。
  5. 完成扣费一致性和幂等测试。

没有完成阶段 A 前,不应上线对外“精确任务成本”。

阶段 B:让 AI 会算

  1. 上线统一 billing query 接口,按筛选返回余额、价目和实际用量。
  2. 技能包新增成本 MCP 工具,由 Agent 自己生成调用计划和报价。
  3. 通用规划协议接入,并完成两个首批验收模板。
  4. 超阈值任务强制预估,批次间检查预算。
  5. 报告附实际用量摘要。
  6. VOC 余额不足时 Agent 默认返回现有支付二维码,同时提供 Balance 链接;模型余额不足由宿主运行时兜底。

阶段 B2:让媒体可持续访问

  1. 统一递归识别 API 返回中的图片、视频和音频。
  2. 生成本地目录和 media-manifest.json
  3. 统一媒体发现和本地缓存,暂不接入个人 Storage 上传。
  4. 报告生成前统一替换为 effectiveUrl
  5. 增加媒体完整性检查和断点续传。

阶段 C:让用户看懂

  1. Balance 页面接入统一 billing query 接口。
  2. Studio 增加总览、用量、规则视图。
  3. 执行追踪/报告/接口下钻。
  4. 充值缺口和二维码闭环。

阶段 D:经营优化

  1. 经营看板接入任务维度。
  2. 对比用户收入和上游成本。
  3. 基于实际数据校准工作流估算系数。
  4. 输出单位有效样本成本和高成本低价值告警。

15. 测试与验收

15.1 后端单元测试

  • 同一路径在不同价目版本下解析正确。
  • 路径规则优先于模块规则。
  • 缓存命中按配置扣费。
  • 日志 quotaactual_cost_cny 和余额变化一致。
  • 5xx 失败不扣费,重试成功只扣一次。
  • 同一幂等键参数变化返回冲突。
  • 普通账户只能查询自己的用量。
  • 共享账户可按 token/client 标签展示,但权限仍以账户为边界。
  • billing query 只能返回当前 Token 所属用户的余额和用量。
  • Agent 传入的 usageTraceId 不能突破当前用户边界。
  • 现有支付订单重复回调不会重复增加 NewAPI 余额。
  • 媒体处理不读取 Storage AK/SK,也不调用线上 Storage 接口。

15.2 技能 smoke

新增覆盖:

  • 无 token 查询公开价目时的产品行为。
  • 有效 token 的余额和估算。
  • 余额不足返回缺口和充值入口,errors=[]
  • 余额不足时能拼接只携带 Token 的现有 Balance 链接,用户在页面内自行选择金额。
  • 默认复用 recharge/order + pay_code2 取得二维码,并同时生成带 Token 的 Balance 自助链接。
  • 模拟支付成功后重新查询余额并从原检查点继续。
  • 280 账号和 134 商品两类计划公式正确。
  • 预算达到 80% 时 warning。
  • 达到硬上限时保存部分结果并停止新增调用。
  • 除用户明确需要的充值直达链接外,普通输出、日志和报告不含 token、Authorization 或请求凭证。
  • voc_api_callusage 与模拟响应头一致。
  • 图片、视频和音频均先写入本地缓存和媒体清单。
  • 所有情况下报告均引用本地文件;失败时不继续使用上游热链。

建议脚本:

scripts/smoke-billing-query.js
scripts/smoke-cost-estimate.js
scripts/smoke-budget-guard.js
scripts/smoke-trend-budget.js
scripts/smoke-usage-report.js
scripts/smoke-recharge-client.js
scripts/smoke-media-pipeline.js

并纳入:

npm run mcp:smoke
npm run smoke:package

15.3 前端验收

  • 余额、今日、7 日、本月金额与 API 返回一致。
  • 模块合计等于总消费。
  • 同一执行追踪下各接口合计等于该次执行总消费。
  • 历史推算记录明确标记,不能伪装成精确值。
  • 移动端表格可横向查看或切换为分组列表。
  • Agent 返回的付费链接打开后不出现登录页,直接进入充值视图。
  • Agent 可以直接返回可扫码支付的二维码。
  • 模型调用返回余额不足时,无需模型继续生成回复,Studio/宿主运行时仍能显示充值入口。
  • 充值后 Balance 余额自动刷新;当前 Agent 会话查询新余额后从原检查点继续。
  • CSV 不包含敏感字段。

15.4 通用能力与首批业务样例验收

所有会发起计费采集的 VOC 技能先通过同一组通用验收:能够生成工作流调用计划、查询同一权威价目、携带 usageTraceId、执行预算保护、处理 VOC 402,并输出可按模块和接口核对的实际账单。下面两个业务场景只作为首批规模化回放样例。

小红书场景:

  • 输入 280 个账号、179 个直链、105 个待匹配账号。
  • 能输出三档计划和逐接口预估。
  • 模拟在第 147 个账号余额不足,账单能精确显示已覆盖和剩余成本。
  • 充值后使用同一 usageTraceId 和本地检查点续跑,不重复扣已完成批次。
  • 账号头像、笔记图片和视频均进入媒体清单,报告使用本地缓存。

天猫场景:

  • 输入 5 页、134 个 SKU、8 个代表 SKU。
  • 经济版不对 134 个商品做全详情/全评论。
  • 标准版能显示全店轻量采集和代表商品深采的成本拆分。
  • 失败版本探测显示尝试次数,但实际消费只按后端扣费日志计算。
  • 商品主图、详情长图、视频和买家秀全部本地缓存,报告引用本地 URL。

16. 监控与告警

上线后至少监控:

  • unpriced_endpoint_count > 0
  • abs(log_cost - quota_converted_cost) > tolerance
  • trace_actual / trace_estimated_high > 1
  • 单次执行失败率、重试率异常。
  • 同一执行追踪重复 requestId 冲突。
  • 用量查询跨账户访问被拒绝。
  • 余额页聚合总额与 NewAPI 用户 used_quota 增量不一致。

17. 兼容与迁移

  • 现有 APIGNewApiBillingMap 保留,作为模块级默认价。
  • 现有 logs 不迁表;新增字段写入 other
  • 历史日志按旧公式展示并标记 mixed
  • 现有 VOC 网关 JSON 响应保持兼容,通过响应头先交付用量。
  • r: Session Token 继续用于用户身份、Balance 免登录和支付授权,但新模式下的数据调用必须映射到该用户的 NewAPI 账户并扣减 NewAPI 通用余额;不能再把 APIGAuth.count 作为正常回退计费路径。
  • 现有余额、充值、订阅入口保持可用,新页面渐进增加用量能力。
  • 现有带 Token 的 Balance 免登录链接、二维码、支付轮询和余额刷新继续复用;Agent 计算建议金额后,默认用于现有二维码建单链路,Balance 链接仍由用户在页面内自行选金额。
  • 已发布报告中的旧远程媒体链接不批量迁移;新任务和续跑任务强制进入媒体流水线。
  • 现有管理员经营看板继续使用独立权限,不下放全局数据接口。

18. 完成定义

本需求完成必须同时满足:

  1. AI 能通过接口读取当前有效计费规则。
  2. 所有已接入计费采集的 VOC 工作流在执行前都能给出可解释的三档预估,首批两个复杂任务通过规模化验收。
  3. 每次实际调用能通过 usageTraceId 关联到报告、技能、步骤和接口。
  4. 余额页能按模块、执行追踪、报告和接口展示调用量与消费。
  5. 大模型与 VOC 数据费用分列,无法精确归集的部分明确标记。
  6. 预算上限能阻止任务继续超支,并保留部分成果。
  7. 用户能看到高成本项、优化建议、预计节省和信息损失。
  8. 充值完成后任务可从检查点继续,不重复已完成调用。
  9. Agent 能直接返回免登录充值链接或支付二维码,用户只需完成支付。
  10. 所有采集多媒体都有本地缓存;本轮不上传线上 Storage。
  11. 除现有充值直达链接所需 Token 外,账户密钥和会话凭证不写入代码、日志、报告或普通工具输出。

18.1 当前验收状态(2026-09-02)

本节是对第 18 节完成定义的代码复核结果,状态以当前工作区和已执行测试为准:

完成定义 状态 复核结论
AI 读取当前有效计费规则 已完成 后端统一 POST /api/fmode/billing/query 返回余额、价目和版本;voc_billing_query/voc_cost_estimate 已注册。
所有已接入工作流执行前三档预估 部分完成 通用规划器覆盖小红书账号监听、天猫 Listing 和自定义 operations;其他新工作流需提供规划适配器。
每次调用关联 usageTraceId/report/skill/step/endpoint 已完成(已接入入口) voc_api_call、小红书/抖音 live 网关请求发送 X-Fmode-* Header,后端写入 logs.other;历史日志标记 mixed/reconstructed。
Balance 按模块、追踪、报告、接口展示 已完成(前端已接入) Studio Balance 用量页调用统一接口,展示调用、quota、实际消费、模块/接口明细和计费规则。
大模型与 VOC 费用分列 部分完成 用户用量账与平台成本报告已拆分;模型侧只有具备同一 trace 的日志才能精确合并。
预算上限阻止超支并保留部分成果 已完成(已接入批处理入口) batch-budget-guard 在小红书/抖音 live 每个关键词批次前读取当前余额与追踪消费,支持 80% 预警、硬预算/余额阻断、差额和建议充值;首批前阻断也会写入 checkpoint.jsonresume 会跳过已完成关键词。经营闭环复用同一趋势入口;跨会话自动唤醒仍由宿主运行时负责。
高成本低价值项优化建议 已完成(首批任务) Agent 估算报告输出 valueScore、可删项和节省额;管理员看板 /usage-diagnostics 已按任务和接口展示成本排行、缓存命中和预计节省。
充值后从检查点继续且不重复调用 已完成(工具级续跑) VOC 402 分支保留部分结果并写检查点;支付后以同一 usageTraceId + resume 续跑,已完成业务键和分页不会重复调用。跨会话自动唤醒仍由宿主运行时负责。
Agent 返回免登录链接或支付二维码 已完成 VOC 402 由统一 recharge client 复用现有 pay_code2/order_status2,二维码失败保留 Token Balance URL;Studio/宿主已对模型 402 直接打开现有充值入口。
采集多媒体并固定本地缓存 已完成(小红书/抖音 live) 通用 discovery/manifest/pipeline 已接入;effectiveUrl 固定为本地路径,线上 Storage 上传已关闭。其他采集入口需继续接入 pipeline。
凭证不写入代码、日志、报告 已完成(静态与 smoke 范围) 请求凭证只作运行时输入,输出经过脱敏;发布包扫描和安装 smoke 通过。

当前可以验收的 P0 交付是:统一报价、真实扣费归集、充值入口、Balance 用量页、管理员任务级成本诊断、两类首批工作流、live 媒体持久化和本地续跑检查点。后续工作集中在“为尚未接入的历史批处理 Skill 增加规划适配器、跨会话自动唤醒、更多采集入口接入媒体流水线、基于真实账号的端到端回放和历史预估校准”,不影响本轮已交付闭环。

19. 建议首个迭代范围

首个可上线迭代建议只做以下闭环:

  1. APIGEndpointPricing 和统一规则解析。
  2. usageTraceId/reportId/stepId 写入 VOC 扣费日志。
  3. 当前账户统一 /api/fmode/billing/query 接口。
  4. 技能包 voc_cost_estimatevoc_usage_report 两个 MCP 工具。
  5. Agent 拼接现有带 Token 的 Balance 链接或返回现有二维码,到账后查询余额并续跑。
  6. 多媒体本地缓存和媒体清单;本轮关闭线上 Storage 上传。
  7. 通用工作流成本规划协议,以及小红书 280 账号、天猫 134 商品两个首批验收模板。
  8. Studio 余额页增加模块拆分、执行记录和接口 Top 消耗。

这个范围已经能回答本次业务提出的三个核心问题:预计多少钱、实际花在哪里、下一次怎么少花但保留关键结果。

20. 代码落地复核与原逻辑影响分析

本节是在对四个仓库的实际代码入口再次核对后形成的落地结论,用于开发排期、任务拆分和代码评审。前文定义产品行为与接口契约,本节明确代码具体落在哪里、如何分阶段接入,以及哪些已有行为必须保持兼容。

20.1 复核结论

整体方案可以落地,但实现时必须遵守以下边界:

  1. 所有任务无论规模大小,都按真实 API/模型调用实时扣除用户 NewAPI 通用余额,不建立任务余额、预付款或一次性任务支付。
  2. usageTraceId 只是 Agent 本地生成并写入日志的执行追踪标签,用于把不同报告的调用频次和实际消费分开;不需要服务端任务表和任务 CRUD。
  3. 报价由 Agent 完成。服务端只通过统一 query 接口提供当前余额、筛选后的有效价目和实际用量,不根据业务类型生成调用计划或最终报价。
  4. 充值中心已有 Token 免登录、余额展示、支付二维码/按钮、支付轮询和到账刷新。本需求复用现有能力:Agent 默认按建议金额组装现有支付请求并返回二维码,另一入口是带 Token 的 Balance 自助链接。
  5. “所有采集多媒体必须缓存”会改变当前 live 工具行为。旧参数继续保留,但 cacheAssets=false 不再允许跳过 live 数据的持久化,assetLimit 只控制报告展示数量,不再控制实际缓存数量。
  6. MCP 使用 stdio 通信,只能在当前 Agent 会话存活时轮询并续跑。真正跨会话自动唤醒需要已有 Agent runtime/callback 或新增后台任务队列,不属于单独修改 VOC 技能包就能完成的能力。
  7. future-server 生产环境通过根目录 server.js 加载 .modules/*.min.cjs。改完模块源码后必须重新构建并更新对应运行时产物,否则现网不会获得新逻辑。
  8. 管理员利润看板和用户 Balance 页是两个权限面。前者可以查看全局经营数据,后者只能查询当前身份对应的用量;不能直接复用管理员接口给普通用户。
  9. r: Session Token 已通过 hasNewApiBillingIdentity() 映射到同一 NewAPI 计费身份;三个 VOC 网关在新模式下使用统一 NewAPI 扣费,APIGAuth.count 仅保留给明确的旧兼容路径。技能端链接、实际扣费和 Balance 用量因此使用同一账户口径。

20.2 仓库与文件修改总表

20.2.1 后端 E:\workspace\server\future-server

类型 文件位置 修改职责 风险
修改 fmode-server/modules/shared/newapi-metering.ts resolveQuota() 扩展为统一规则解析;真实扣费、日志金额和响应计费信息使用同一解析结果;写入任务追踪字段
修改 fmode-server/modules/shared/newapi-metering.ts 集中完成 sk-/r: 身份解析、Session-to-NewAPI 映射、路径级价目匹配、额度检查、幂等扣费、实际金额和追踪日志写入
修改 fmode-server/modules/voc-social-api/src/routes.ts 接收白名单任务上下文、按路径解析价格、写日志、返回 usage 响应头
修改 fmode-server/modules/voc-e-commerce/src/routes.ts 与社媒网关保持相同计费和追踪行为
修改 fmode-server/modules/voc-ecom-api/src/routes.ts 与社媒网关保持相同计费和追踪行为
修改 fmode-server/api/routes.ts 在现有主路由中提供统一 POST /api/fmode/billing/query;媒体 Storage 路由不由本技能包调用
修改 三个模块的构建脚本或 scripts/build.mjs 确保共享计费代码进入产物,并复制到根目录 .modules
生成 .modules/voc-social-api.min.cjs.modules/voc-e-commerce.min.cjs.modules/voc-ecom-api.min.cjs 三个 VOC 网关的生产实际加载产物;由各模块构建生成,不手工编辑。billing 路由随 fmode-server/api/routes.ts 加载,不单独生成 CJS
保持并复用 api/api-ncloud/fmode/routes.js/recharge/order Agent 和 Balance 页创建或复用充值订单及 AccountLog
修改并复用 api/api-ncloud/fmode/sync-fmode-api.jsnewapi-user-resolution.js 抽取可被计费模块复用的 Session 用户到 NewAPI 用户映射;保持 syncUser() 和 Token 创建幂等
保持并回归 api/api-ncloud/fmode/serv-user.jsroutes.jscloud/user/auth-route.js 继续承担现有钱包、NewAPI 划拨、pay_code2 二维码和 order_status2 状态,不引入任务支付绑定
修改 api/api-ncloud/profit/service/revenue.service.js 管理员聚合优先读取新的实际金额、任务和路径字段,保留历史兼容公式
修改 api/api-ncloud/profit/routes.js 增加管理员执行追踪/报告/接口聚合,不改变现有鉴权
新增 后端迁移脚本 创建 APIGEndpointPricing 和 NewAPI 日志查询所需索引,不创建任务支付表
新增 后端单元及集成测试 覆盖用户隔离、查询筛选、价格一致性、扣费幂等和历史日志兼容

注意:AuthService.guardAuthToken() 负责入口鉴权,统一计费身份和价目解析集中在 shared/newapi-metering.ts。billing query 强制使用当前请求解析出的 userId,筛选条件只能作为附加条件,不能跨用户查询。

20.2.2 VOC 技能包 E:\workspace\openclaw-voc-skill\claude-code\claude-code-voc-intelligence

类型 文件位置 修改职责 风险
修改 mcp/src/core/credentials.js 将字符串式 Token 读取改为类型化凭证上下文,分别返回 newApiTokensessionToken、来源和可用能力,禁止把任意 vocToken 当成可拼 Balance 链接的 Session
修改 mcp/src/core/payment-links.js 增加 Tokenized Balance URL 构造和统一充值结果;旧 APIG/workshop helper 仅保留给旧产品流程
新增 mcp/src/core/billing-client.js 封装统一 billing query 请求;按场景选择 balance/pricing/usage,统一隐藏凭证和底层错误
修改 mcp/src/providers/voc-gateway.js 接收类型化双凭证、发送追踪头、返回实际认证/计费模式并读取 usage 响应头;统一 401/402/403
修改 mcp/src/providers/ecommerce-gateway.js 与 social provider 保持同一认证、计费、错误和响应上下文
修改 mcp/src/providers/overseas-gateway.js 与 social provider 保持同一认证、计费、错误和响应上下文
修改 mcp/src/providers/xiaohongshu-api.jsdouyin-api.js 移除独立请求/错误分类,改为复用统一 social gateway;保留平台便捷方法
修改 mcp/src/features/xiaohongshu-trend/live-collector.jsdouyin-trend/live-collector.js 传递完整凭证和 usage context,保留结构化错误类型、requestId 与部分进度
新增 mcp/src/core/usage-context.js 本地创建和传递 usageTraceId/reportId/skillId/workflowType/stepId/clientId
新增 mcp/src/features/voc-cost/workflow-planner.jsestimate-report.js 生成经济版、标准版、完整版调用计划、成本区间和用户可读报价
新增 mcp/src/core/budget-guard.js 批次执行前检查余额和预算,输出差额、充值建议及检查点
新增 mcp/src/core/recharge-client.js 计算差额后默认调用现有建单/支付码链路返回二维码,同时提供带 Token 的 Balance 自助链接,并在到账后查询余额
新增 mcp/src/features/media/media-pipeline.js 发现图片/视频/音频,下载、去重、校验、写 manifest 并固定使用本地 effectiveUrl
新增 mcp/src/features/media/media-discovery.js 从不同接口的嵌套响应中按字段映射和 MIME 类型发现媒体,避免用单一字段名硬编码
修改 mcp/src/features/xiaohongshu-trend/assets.js 迁移到通用媒体流水线;保留旧导出作为兼容适配器
修改 mcp/src/tools/voc-api-catalog-run.js 支持任务上下文、usage、默认输出目录和通用媒体副作用
修改 mcp/src/tools/xiaohongshu-trend-run.js 接入预估、预算、检查点、全量媒体缓存和充值续跑
修改 mcp/src/tools/douyin-trend-run.js 与小红书工作流保持同一规则
修改 mcp/src/features/voc-business-workflow/business-workflow.js 汇总大模型费用与 VOC 数据费用,输出成本价值建议
修改 mcp/src/features/fmode-image-analysis/image-analysis.js 复用统一错误分类与 NewAPI 充值结果;严格区分模型 402 和权限 403
修改 mcp/src/core/result-envelope.js 给所有工具统一增加 usage/estimate/recharge/checkpoint 可选字段,保持原字段兼容
修改 mcp/src/core/api-catalog.jsmcp/catalog/voc-social-endpoints.jsonmcp/catalog/params/*.json 使用稳定 endpoint 标识和计费单位元数据;删除把 billing: 1 当人民币价格的行为,价格始终来自 billing query
新增 mcp/src/tools/voc-cost-estimate-run.js MCP voc_cost_estimate 的实现
新增 mcp/src/tools/voc-usage-report-run.js MCP voc_usage_report 的实现
修改 mcp/src/server.js 注册新工具和 schema;调整 cacheAssets/assetLimit 描述及兼容语义
修改 mcp/src/core/activation.js 缺 Token 时只做配置恢复,不再打开旧 APIG 充值页;只在确认 402 且存在 Session 时生成个人充值入口
修改 skills/voc-api-catalog/SKILL.md 加入执行前估算、批次预算检查、余额不足返回支付入口、媒体强制持久化规则
修改 skills/xiaohongshu-trend-intelligence/SKILL.mdskills/douyin-trend-intelligence/SKILL.md 补充成本和媒体行为,不要求用户理解内部参数
修改 其他所有会发起计费采集的 skills/*/SKILL.md 或统一入口 Skill 引用同一成本规划、追踪和 VOC 余额不足规则,避免能力只覆盖两个验收样例
修改 skill-package-manifest.jsonpackage.json 登记新工具、脚本和能力说明
修改 scripts/smoke-mcp.jsscripts/smoke-package.js 覆盖工具发现、结构化输出、敏感信息、充值和媒体兼容
新增 scripts/smoke-cost-estimate.jssmoke-recharge-client.jssmoke-media-pipeline.js 独立验证 Agent 报价、现有充值入口衔接和媒体流水线

voc_api_call 是通用入口,不能假设所有接口都有统一媒体字段。首期由 endpoint catalog 增加可选 mediaFields 映射;未登记接口再使用受限的 URL/MIME 发现器,并把无法确认的候选项写入 warning,避免把普通链接误当作文件下载。

20.2.3 Studio E:\workspace\fmode-studio

类型 文件位置 修改职责 风险
新增 projects/fmode-studio/src/components/billing-center.service.ts 封装统一 billing query,供余额、规则和用量视图使用
新增 projects/fmode-studio/src/components/billing-usage.component.ts 展示模块、执行追踪、报告和接口用量
保持并回归 projects/fmode-studio/src/app/app.routes.tsauth-guard.service.ts 复用已确认的 /balance 路由和 token/session 免登录识别;保持消费 Token 后清理地址栏
修改 projects/fmode-studio/src/modules/launcher/fmode-home.component.ts 保持现有 Balance 打开方式并接入用量视图
修改 projects/fmode-studio/src/components/balance-modal.component.tsbalance-page.component.ts 保留现有余额、二维码、支付轮询和到账刷新,只接入用量子组件
修改 projects/fmode-studio/src/modules/codex-workspace/pages/codex-shell/* 保持 Codex 工作区打开余额页的现有行为,并接入新用量视图
修改 projects/fmode-studio/src/modules/codex-workspace/pages/codex-shell/codex-shell.component.ts 及模型请求错误适配层 拦截模型调用 402,在不依赖 Agent 回复的情况下直接打开现有 Balance 充值入口
新增 对应 *.spec.ts 回归 Token 免登录、自助选金额、二维码、支付轮询、到账刷新和用量展示

Studio 仓库当前这些相关文件已有未提交修改。实际编码必须以当前工作树为基线做增量编辑,不能覆盖或回退既有改动。

20.2.4 管理员看板 E:\workspace\voc-profit-web

类型 文件位置 修改职责 风险
修改 client/src/app/api.service.ts 扩展管理员任务、报告、接口、价格版本和数据质量类型及请求
修改 client/src/app/dashboard.component.ts 增加任务成本排行、接口 Top 消耗、估算偏差和低价值高成本诊断
修改 client/src/app/dashboard.component.html 在现有“模块转发明细”上补任务/报告视角,不复制 Balance 用户页
修改 client/src/app/dashboard.component.scss 支持新增表格和筛选状态
可选修改 client/src/app/app.routes.ts 若单独增加任务成本页面则新增路由;首期可复用现有 modules 页面

voc-profit-web/server/src/index.ts 只是静态站点和 /api/profit 路由装载器,业务聚合仍在 future-server/api/api-ncloud/profit。首期没有新增服务器逻辑时无需修改该文件。

20.3 后端具体实施方案

20.3.1 统一计费规则和真实扣费

一次 VOC 网关请求按以下顺序处理:

  1. 严格认证并只从认证结果取得 userId/tokenId
  2. 规范化 model + method + proxyPath,移除 query 和动态值。
  3. resolveBillingRule() 读取当前生效的路径规则;找不到时按现有模块映射回退,并标记 matchedBy=fallback
  4. assertNewApiQuotaAvailable()chargeNewApiUsage() 接收同一个 ResolvedBillingRule 对象,避免检查额度和实际扣费使用不同价格。
  5. 上游或缓存请求成功后仅扣一次;重试使用同一 requestId/idempotencyKey
  6. 将实际 quotaactual_cost_cny、价格版本和任务字段写入 logs.other
  7. 返回兼容的原 JSON,同时增加非敏感 usage 响应头。旧客户端不读取响应头也不受影响。

不能让网关先按 pathQuota 扣费、日志再按 APIGNewApiBillingMap.price_cny 记另一金额。规则解析结果必须是额度检查、扣除、日志和展示四处共享的唯一对象。

20.3.2 当前账户用量查询

POST /api/fmode/billing/query 不调用管理员 profit API,而是直接基于严格解析出的当前 userId 查询 NewAPI logs

  • 查询条件强制包含 user_id = currentUserId
  • usageTraceId/reportId 只能作为附加条件,不能替代用户条件。
  • groupBy 使用服务器白名单映射到固定 SQL 表达式,不能把客户端字段直接拼进 SQL。
  • 新日志读取 actual_cost_cny;旧日志回退 price_cny 或 quota 换算,并返回 quality=mixed/reconstructed
  • from/to、分页大小和最大时间范围设置上限,避免 Balance 页形成大范围全表扫描。
  • 建议索引至少覆盖 logs(user_id, created_at),并评估 otherusage_trace_id/report_id 的表达式索引或结构化列。

20.3.3 Agent 与现有充值中心衔接

不新增任务支付会话,按以下方式衔接现有充值中心:

  1. Agent 调用 billing query 取得当前余额和价目,根据本地剩余计划自行计算差额和建议充值金额。
  2. 默认按建议金额调用现有 /api/fmode/recharge/order 创建或复用订单,再调用 pay_code2 取得支付码并返回二维码。
  3. 另一入口拼接 balance/?token=USER_TOKEN;用户打开后在现有页面自行选择金额。
  4. BalanceModalComponent.startPayment()pay_code2order_status2、钱包账本和 topUpNewApiQuota() 继续按现有链路运行。
  5. 充值到账后,Balance 页面继续使用现有逻辑刷新余额。
  6. 当前 Agent 会话再次调用 billing query;余额足够后从 usageTraceId 对应的本地检查点继续。

充值只增加 NewAPI 通用余额,不记录为某个 usageTraceId 的任务收入。现有支付链路仍需保持 tradeNo 幂等,但这属于原充值能力的回归要求,不是新增任务支付模型。

20.3.4 本地媒体缓存

媒体处理只保留本地事实层:

  • 下载成功即形成可交付的本地事实,计算 sha256 并写入目标文件。
  • 相同 sha256 在同一任务内只保留一份实体文件,manifest 可以有多个业务引用。
  • effectiveUrl 固定为本地相对路径,HTML 报告和标准化 JSON 均不引用线上地址。
  • cloudUrl 固定为 nulluploadStatus 固定为 disabled_local_only
  • 不调用 storage/profile、预签名上传或 complete 接口,避免产生线上 Storage 流量。
  • 下载失败记录原因并清空展示地址;报告不回退到上游热链。

20.4 Studio 具体实施细节

20.4.1 URL 与凭证处理

复用需求方确认的现有 Balance 路由:

https://app.fmode.cn/dev/studio/balance/?token=USER_TOKEN

加载顺序:

  1. 页面读取 token 并复用现有免登录识别逻辑取得当前用户。
  2. 用户在现有金额选项中自行选择充值金额。
  3. 继续使用现有余额查询、二维码、支付按钮、订单轮询和到账刷新。
  4. Token 不出现在日志、分析事件、页面正文或错误信息中;现有页面识别完成后已从可见地址栏移除。

远端 origin/master 已确认 auth-guard.service.ts 同时接受 tokensession,调用 Parse.User.become(token) 后清理地址栏;app.routes.ts 已存在 /balance 路由。当前本地分支落后且有重叠的未提交改动,实际编码时以现有工作树为基线合并这些远端行为,不重建支付页面,也不覆盖本地修改。

20.4.2 普通充值与 Agent 充值并存

  • 普通登录用户仍可从 BalanceModalComponent 手动选金额并调用原 startPayment()
  • Agent 自助链接进入同一个 Balance 页面,通过 Token 免登录后由用户选择金额。
  • 两种入口使用完全相同的支付供应商、账务入账和 NewAPI 划拨服务。
  • balance-modal.component.ts 已承担余额、支付、订阅和轮询等职责;新增用量查询和展示应下沉到 service 和子组件,不改写现有支付主体。

20.5 技能包具体实施细节

20.5.1 参数兼容迁移

现有参数 当前语义 新语义 兼容行为
cacheAssets 是否缓存少量首图 是否在报告中展示缓存媒体的兼容开关 sample 模式可按旧值;live 模式始终持久化,传 false 时返回弃用 warning
assetLimit 最多缓存多少张首图,最大 30 报告最多展示多少项媒体 不限制实际缓存;schema 可保留原字段名并新增 mediaDisplayLimit
output trend 工具输出目录 报告和媒体根目录 保持兼容
无输出目录的 voc_api_call 只返回 JSON 默认创建任务输出目录和 manifest 可通过结构化 files 告知目录,不改变原始 data.result

默认目录建议为工作区下 .voc/runs/<usageTraceId>/ 或现有 output 根目录下的 <usageTraceId>/。路径选择必须由统一 helper 完成,不能由各工具分别拼接。

20.5.2 检查点和防重复调用

每个批次写入检查点:

{
  "usageTraceId": "USAGE_TRACE_ID",
  "stepId": "collect_account_notes",
  "completedItemKeys": ["ITEM_KEY"],
  "nextCursor": "CURSOR",
  "requestIds": ["REQUEST_ID"],
  "mediaManifestPath": "assets/media-manifest.json",
  "updatedAt": "ISO_TIME"
}

续跑前先读取检查点和后端任务实付记录:

  • 已完成的业务键不再请求。
  • 状态不确定但已有成功 requestId 的调用不再扣费重放。
  • 上游返回失败且后端没有成功扣费记录时才进入重试队列。
  • 支付只解除预算或余额阻断,不重置任务和分页游标。

20.5.3 自动续跑能力分级

等级 行为 所需改动 首期
L0 支付完成后用户回到 Agent 触发继续 现有余额刷新 + 本地检查点 保底能力
L1 当前 Agent 会话周期性查询 billing query,余额到账后续跑 技能 recharge-client + 当前进程存活 P0 目标
L2 Agent 会话关闭后,支付回调唤醒后台任务并跨会话续跑 Agent runtime/callback、持久任务队列、回调签名和执行租约 后续独立迭代

产品文案中的“充值完成后自动继续任务”在 P0 指 L1。若要求用户关闭聊天或进程后仍自动生成报告,则验收目标必须升级为 L2,并明确增加运行时仓库或服务端任务执行器的改造范围。

20.6 原逻辑影响矩阵

原有能力 影响方式 兼容策略 必测回归
VOC 网关 JSON 响应 增加日志字段和响应头,不改主 JSON 旧客户端忽略新响应头 三通道正常、缓存、上游失败、重试
NewAPI 扣费 路径级规则替代部分模块级默认价 无路径规则时回退现有映射;灰度比对后启用扣费 额度检查与实际扣除一致、重复请求幂等
NewAPI 历史日志 不迁移、不回写 查询时标记 mixed/reconstructed 新旧日志合并金额和质量标识
普通余额查询 增加模块/执行追踪/接口视图 现有余额和订阅接口继续可用 余额总额、充值记录、订阅显示
现有充值中心 不重做;默认 Agent 直出二维码,Token 链接供用户自助选金额 保留原 Balance、二维码、轮询和到账刷新 免登录、自助选金额、建单、扫码、到账
支付回调划拨 不改变业务模型 继续复用 topUpNewApiQuota() 和原账本 重复回调、超时回调、部分失败补偿
trend 图片缓存 从少量首图变为 live 全媒体 旧导出保留适配;展示上限与缓存上限分离 图片、视频、音频、失败降级
voc_api_call 增加任务目录和媒体副作用 data.result/raw 结构保持 已登记和 rawPath 接口、无媒体接口
报告媒体地址 新报告改用本地 effectiveUrl 旧报告不批量迁移 本地浏览、断网展示
管理员利润看板 增加任务/接口维度 保持管理员鉴权,不复用到用户侧 全局数据完整、历史公式兼容

风险排序:

  • 高风险:身份隔离、真实扣费、价格一致性和用户用量越权。
  • 中风险:Balance 聚合、任务检查点、媒体下载、报告 URL 替换、模块构建部署。
  • 低风险:新增展示字段、CSV 导出、技能说明和能力清单。

20.7 明确不调整的原有逻辑

首期明确不做以下改动:

  1. 不替换现有支付供应商,也不取消普通登录用户的充值入口。
  2. 不创建一套独立的 VOC 钱包,不绕开现有钱包和 NewAPI quota 划拨。
  3. 不把管理员 /api/profit 权限或全局用户数据下放给 Balance 页面。
  4. 不批量迁移或重写历史 NewAPI 日志;历史账单只做查询时兼容解释。
  5. 不批量抓取和迁移已经发布的旧报告媒体;只约束新任务和续跑任务。
  6. 不把 Storage AK/SK、支付商户密钥或用户 Token 写入技能文件、报告、日志和分析事件。
  7. 不改变三个 VOC 网关的上游接口选择和原始业务响应结构。
  8. 不把 clientId/skillId 当作强身份依据;真正的账户边界始终来自服务端认证结果。

20.8 建议提交拆分与上线门禁

为降低高风险逻辑互相干扰,建议按以下提交和发布单元推进:

  1. 计费只观测:路径规则解析、任务字段和 usage 响应头先写影子金额,不改变扣费;对比现有 quota。
  2. 计费生效:灰度启用路径级扣费,开启差异告警和一键回退到模块级价格。
  3. 用户账单:上线严格用户隔离的统一 billing query,先供内部账户验证。
  4. 技能估算:发布 voc_cost_estimate、预算检查和通用工作流计划协议,以小红书和天猫模板完成首批验收,不接支付。
  5. 充值衔接:验证现有 Token 直达、自助选金额、Agent 按建议金额生成二维码和到账刷新;只补 Agent 调起方式,不重做支付。
  6. 当前会话续跑:接入检查点和 L1 自动续跑,验证中断后不重复采集。
  7. 媒体流水线:先用小红书/抖音工具完成灰度验证,再在同一 P0 发布门禁前覆盖通用 voc_api_call 和其他计费采集入口。
  8. 看板:Studio 面向用户展示;voc-profit-web 增加管理员成本优化分析。

每个发布单元必须具备独立开关或回退点:

  • 路径级计费可回退模块级价格。
  • Agent 直达链接异常时仍可从现有 Balance 入口充值。
  • 媒体处理始终保留本地缓存交付,不产生线上上传流量。
  • 新用量聚合异常时不影响实际调用和扣费。
  • L1 续跑异常时任务保持 partial,可从检查点人工继续。

20.9 最终交付物

完成实施后应交付以下可验收成果,而不只是代码提交:

  1. 四个仓库的分仓代码变更和变更说明。
  2. 数据结构迁移脚本、路径级初始价目表和价格版本说明。
  3. 统一 billing query 和现有充值调用链文档及可执行示例;媒体仅提供本地缓存说明。
  4. VOC 技能包新版本、安装包和 MCP 工具清单。
  5. 通用 VOC 工作流的执行前估算、执行中预算状态和执行后账单样例,并附小红书 280 账号与天猫 134 商品两类首批验收结果。
  6. 免登录支付链接与支付二维码的桌面端、移动端验收录像或截图。
  7. 支付成功后当前会话自动续跑、重复回调不重复到账的测试证据。
  8. 图片、视频、音频的本地缓存样例及对应 media-manifest.json
  9. Studio 用户用量页和 voc-profit-web 管理员成本优化视图。
  10. 自动化测试结果、灰度发布步骤、监控项和回滚手册。

21. 现有技能包计费链路审计与完整修改清单

本节以当前代码实际执行路径为依据,补全“改哪些位置才能让新模式真正跑通”。结论是:计费和充值逻辑目前分散在通用接口目录、两个平台趋势工具、业务闭环、图片分析、Token 检查和激活流程中。只修改 voc_api_call 或只替换一处充值 URL,无法覆盖实际报告任务。

21.1 当前端到端链路

21.1.1 通用 voc_api_call

当前过程:

  1. credentials.js 分别尝试读取 NewAPI sk- Token 和 VOC Token,但 VOC Token 返回值没有类型保证。
  2. voc-api-catalog-run.js 优先把 sk- 传给 social/ecommerce/overseas gateway,同时把另一个 Token 作为鉴权失败回退。
  3. 三个 provider 只有在第一次请求被分类为 auth 时才使用回退 Token;402 和 403 不回退。
  4. 后端收到 sk- 时通过 newapi-metering.ts 扣减 NewAPI 用户和 Token quota,并写 NewAPI logs
  5. 后端收到 r: 时走旧 APIGAuth.count 查询和扣减,不进入同一 NewAPI 日志。
  6. NewAPI 402 回到工具后,当前仍生成固定 Studio 旧入口;Session 分支和部分错误分支仍生成旧 APIG/workshop 链接。

这条链路已经能区分大部分 401、402、403、参数和上游错误,但还不能保证“同一用户统一 NewAPI 余额、统一账单、统一充值入口”。

21.1.2 小红书和抖音趋势报告

两个 trend runner 当前先执行:

readNewApiToken(input) || readVocToken(input)

这会把两种凭证压缩成一个字符串。后续 live-collector.js 分别实例化 XiaohongshuApiDouyinApi,它们没有携带另一种凭证,也没有复用通用 gateway 的回退结果和 usage 响应。因此存在以下后果:

  • sk- 鉴权失败后不能可靠用 Session 身份继续。
  • 专用 API 类和通用 gateway 的错误分类可能不同。
  • 402、403 和包含“权限/余额”的历史返回会被 trend runner 二次猜测。
  • 全失败和部分成功后的充值分支多次调用 buildVocRechargeInfo(),继续返回旧 APIG/workshop 入口。
  • 部分报告只保存采集数据,没有统一 usageTraceId、实付金额、检查点和可续跑状态。

21.1.3 业务闭环和图片分析

  • voc-business-workflow 调用 trend runner;非 ok 时会包一层业务提示。它会保留底层文本,但没有稳定透传 recharge/usage/estimate/checkpoint,以后很容易在包装时丢链接或二维码。
  • fmode-image-analysis 直接调用模型网关,并把 HTTP 402 和 403 都当成 needs_recharge;同时使用旧 buildVocRechargeInfo()。这会把权限问题错误引导到充值,并且无法和 VOC 数据费用使用同一结果协议。
  • Agent 自身的大模型请求在余额耗尽时,模型可能已经不能生成下一条回复。这个场景必须由 Studio/Agent runtime 拦截 402 并打开现有 Balance 页面,不能只依赖 Skill 返回链接。

21.1.4 Token 检查和激活

  • mcp/src/server.js 中的小红书/抖音 Token check 目前主要判断“是否读到字符串”,不验证 Token 类型、有效性、NewAPI 余额和 Session 是否能生成个人充值入口。
  • 两个平台的 Token 选择顺序不完全一致。
  • activation.js 在缺 Token 时会构造旧 workshop/APIG 页面。缺 Token 属于配置恢复,不能等同于余额不足。
  • 只有经过类型校验的 r: Session Token 才能放进 balance/?token=...sk-、空值或任意 vocToken 都不能用于拼个人链接。

21.1.5 当前价目和额度口径

当前目录和后端规则的实际情况如下:

位置 当前事实 新模式处理
mcp/catalog/voc-social-endpoints.json 共 1,344 个接口:social 1,018、ecommerce 289、overseas 37 目录只保存稳定 endpoint 和计费单位元数据,不作为价格权威源
social 目录 1,018 个接口没有 endpoint 级 billing 必须通过 billing query 按 endpoint 筛选读取服务端有效价目
ecommerce/overseas 目录 326 个接口多数写有 billing: 1 只表示一次调用单位,不能解释为 ¥1 或真实 quota
newapi-metering.ts quota 优先级为 model:path pathQuota -> pathQuota -> options.quota -> modelQuota -> APIGNewApiBillingMap.quota -> 默认值 统一收敛为 resolveBillingRule(),检查、扣费、日志和展示共享结果
NewAPI quota 检查 同时检查用户总 quota 和 Token remain quota;任一不足返回 402 保持双重额度约束,并在 billing query 返回可解释的可用余额
人民币换算 quota / 500000 * USDExchangeRate;充值反向换算 保持现有 NewAPI 换算权威,价格版本记录汇率和换算基准
缓存 当前三个 VOC 模块均可能对缓存命中计费 将政策写入 endpoint 规则并在报价、实扣和账单中明确展示

因此,Agent 的成本公式只能是“计划调用单位 × billing query 返回的当前单价”,不能是“目录 billing 字段 × 调用数”。实际消费以 NewAPI 成功扣费日志为准。

21.2 必须修复的计费冲突

21.2.1 Session 回退必须统一扣 NewAPI

目标语义不是“sk- 扣 NewAPI,r: 扣旧 VOC 次数”,而是:

请求凭证 身份解析 数据调用扣费 充值用途
有效 sk- NewAPI tokens -> users 当前 NewAPI 用户通用余额 若同时有 Session,可返回个人 Balance 链接和二维码
有效 r: Parse _Session -> _User -> NewAPI users.parse_id 映射后的同一 NewAPI 用户通用余额 可生成 Tokenized Balance 链接并授权现有支付链
sk- 401 且 r: 有效 改用 Session 身份解析 仍扣映射后的 NewAPI 用户通用余额 同上
无有效凭证 不建立计费身份 不发起数据调用 返回配置/登录恢复状态,不伪造个人链接

后端需要把计费函数从“只接受请求头里的 sk-”改成“接受严格解析后的 NewApiBillingPrincipal”。建议统一 principal:

type NewApiBillingPrincipal = {
  authMode: "newapi_token" | "session_newapi";
  userId: number;
  tokenId: number;
  parseUserId?: string;
  group: string;
};

assertNewApiQuotaAvailable()chargeNewApiUsage()、日志写入和 billing query 都使用该 principal。Session 分支可以复用 syncUser() 已有的 users.parse_id 映射和 Token 幂等创建能力,但不能把解析出的 NewAPI Token 返回给普通数据响应或写入日志。

切换新模式后,三个 VOC 网关的正常请求路径不再调用:

  • getApiAuth()
  • deductApiAuthCount()
  • APIGAuth.count 的余额检查。

这些函数可以在迁移期受开关保护以便回滚,但不能和 NewAPI 同时扣费。上线前必须用同一 Session 用户验证:NewAPI quota 减少、NewAPI 日志新增、旧 APIGAuth.count 不变。

21.2.2 单价、检查、实扣和账单必须共用一个规则

当前 newapi-metering.ts 的 quota 解析依次考虑路径配置、显式 quota、模型配置、模块映射和默认值,但日志中的 price_cny 可能仍来自模块级 APIGNewApiBillingMap。新模式应在请求开始时只解析一次:

type ResolvedBillingRule = {
  endpointId: string;
  model: string;
  method: string;
  normalizedPath: string;
  unit: "call" | "item" | "page" | "token";
  quota: number;
  unitPriceCny: number;
  pricingVersion: string;
  cachePolicy: "charged" | "free" | "discounted";
  matchedBy: "endpoint" | "module" | "fallback";
};

额度预检、真实扣减、logs.other.actual_cost_cny、响应 usage 和 Balance 展示必须使用同一个对象。mcp/catalog/voc-social-endpoints.json 里的 billing: 1 只能表示历史调用单位,不能再被 Agent 当作人民币价格。

21.2.3 业务成功后才扣一次

三个 VOC 网关需要统一以下顺序:

  1. 认证并解析 principal。
  2. 解析价格并预检额度。
  3. 查询缓存或调用上游。
  4. 通过统一 isBillableBusinessSuccess() 判断业务响应成功。
  5. 使用 requestId + principal.userId + endpointId 幂等扣费。
  6. 写实际日志并返回 usage。

缓存是否计费由 ResolvedBillingRule.cachePolicy 决定,不能由三个路由各自硬编码。上游 HTTP 成功但业务 code 失败、参数错误、权限错误和最终失败的重试不能产生成功扣费日志。

21.3 类型化凭证和统一状态机

mcp/src/core/credentials.js 应返回凭证上下文,而不是让每个工具自行 A || B

{
  newApiToken: "<secret-or-empty>",
  sessionToken: "<secret-or-empty>",
  sources: {
    newApiToken: "request|env|claude-settings|fmode-config|none",
    sessionToken: "request|env|credential-file|none"
  },
  capabilities: {
    canCallWithNewApi: true,
    canCallWithSessionIdentity: true,
    canBuildPersonalBalanceUrl: true,
    canCreatePaymentOrder: true
  }
}

所有入口使用同一状态机:

条件 工具状态 Agent 动作
没有任何可用调用凭证 needs_token 返回配置或登录恢复步骤;不称为余额不足,不生成个人链接
凭证存在但认证失败 needs_valid_token 返回凭证恢复步骤;不生成充值二维码
402 且有有效 Session needs_recharge 返回差额、建议金额、Tokenized Balance 链接;Agent 传 createPaymentQr=true 时复用现有支付链生成二维码
402 但没有 Session needs_session 保留检查点并返回登录/Session 恢复入口;不拼假链接
403 needs_permission 提示账号或接口权限处理,不引导充值
参数错误 needs_input 返回缺失字段和参数文档,不引导充值
上游失败 upstream_unstable 按规则重试或保留部分结果,不引导充值
余额足够 ok 或继续执行 带追踪上下文执行并记录实付

其中 needs_session 是充值交互所需身份缺失,不代表数据账户没有余额。若产品不希望增加对外状态,也可以对外仍用 needs_token,但结构化 summary.errorKind 必须是 missing_session_for_recharge,避免 Agent 把它解释成 402。

21.4 Agent 链接和二维码输出协议

所有计费工具的充值输出统一进入 recharge,业务工作流只能透传或补充说明,不能重新拼 URL:

{
  "status": "needs_recharge",
  "assistantMessage": "当前余额不足,还差 ¥12.40,建议充值 ¥20.00。可直接扫码支付,或打开个人充值页面。",
  "summary": {
    "shortageCny": 12.4,
    "suggestedRechargeCny": 20,
    "completedItems": 147,
    "remainingItems": 133
  },
  "recharge": {
    "paymentMode": "qr_and_balance_url",
    "balanceUrl": "https://app.fmode.cn/dev/studio/balance/?token=USER_TOKEN",
    "qrCodeUrl": "QR_CODE_URL",
    "qrImagePath": "OUTPUT_QR_IMAGE_PATH",
    "tradeNo": "TRADE_NO",
    "polling": {
      "supported": true,
      "status": "pending"
    }
  },
  "checkpoint": {
    "usageTraceId": "USAGE_TRACE_ID",
    "path": "CHECKPOINT_PATH",
    "canResume": true
  },
  "files": ["OUTPUT_QR_IMAGE_PATH", "CHECKPOINT_PATH"],
  "nextActions": ["完成支付后继续当前任务"],
  "warnings": [],
  "errors": []
}

规则:

  1. shortageCny = max(estimatedRemainingHighCny - currentBalanceCny, 0)
  2. suggestedRechargeCny 由 Agent 根据差额、平台允许金额档位和小幅缓冲计算,传给现有建单链路;它不是服务端报价,也不绑定任务。
  3. balanceUrl 不携带金额。用户进入现有 Balance 页后自行选择充值金额。
  4. 二维码路径复用 /api/fmode/recharge/order -> pay_code2 -> order_status2voc_billing_querycreatePaymentQr=true 时由技能包调用现有支付码链路并返回 qrCodeUrl。这三个是现有接口,不计入新增接口数。
  5. 只新增 POST /api/fmode/billing/query。报价、差额和建议金额均由 Agent 基于该接口返回的数据计算。
  6. 在工具输出和持久化物中,Session Token 只允许出现在最终明确交付给当前用户的 balanceUrl;运行时仍可放入 HTTPS 请求的认证头或现有支付请求。日志、诊断、usage、报告正文、二维码文件名、tradeNo、埋点和错误信息必须脱敏。
  7. 如果二维码创建失败但 Session 有效,仍返回 Tokenized Balance 链接和检查点,paymentMode=balance_url
  8. 支付到账后重新调用 billing query;余额达到继续条件时从检查点续跑,不重置分页、不重复调用已完成项。

21.5 技能包逐文件修改清单

21.5.1 核心层

文件 必须修改的行为
mcp/src/core/credentials.js 增加 readCredentialContext() 和 Token 类型校验;保留旧 reader 作为兼容包装;明确 Session 来源,禁止把 sk- 作为 Balance Token
mcp/src/core/payment-links.js 新增 buildTokenizedBalanceUrl(sessionToken);新增统一 recharge formatter;旧 APIG/workshop URL 只供明确的旧产品流程,不再用于 NewAPI 402
mcp/src/core/billing-client.js 调用唯一 billing query;支持 include、endpoint 筛选、追踪筛选;返回结构化 balance/pricing/usage
mcp/src/core/usage-context.js 创建并传递 usageTraceId/reportId/skillId/workflowType/stepId/requestId;写本地运行元数据
mcp/src/core/budget-guard.js 接收 Agent 计划和价格,计算三档预估、剩余成本、差额、建议充值金额;批次前阻断超预算
mcp/src/core/recharge-client.js 使用 Session 调现有建单、支付码、状态查询;写二维码文件;返回 Tokenized URL;到账后刷新余额并触发 L1 续跑
mcp/src/core/result-envelope.js 在保持现有字段的前提下统一可选 usage/estimate/recharge/checkpoint;确保失败友好状态 errors=[]
mcp/src/core/activation.js 缺 Token 只返回配置恢复;确认 402 才进入统一 recharge;移除默认打开旧 APIG/workshop 页的行为

21.5.2 Provider 和采集层

文件 必须修改的行为
mcp/src/providers/voc-gateway.js 接收 credential context;携带追踪头;记录实际 authMode/billingMode;响应返回 usage;401 时才尝试 Session 身份;402/403 不混淆
mcp/src/providers/ecommerce-gateway.js 复用同一个 callGateway() 或公共基类,只保留根地址与 envelope 差异
mcp/src/providers/overseas-gateway.js 复用统一调用器,同时保留 /forward 请求封装
mcp/src/providers/xiaohongshu-api.js 删除独立 fetch/error classifier,改用 social gateway;每个便捷方法传 endpoint、credential context 和 usage context
mcp/src/providers/douyin-api.js 与小红书相同,保证两个平台专用路径不再绕过统一计费和充值逻辑
mcp/src/features/xiaohongshu-trend/live-collector.js 不再只收一个 token;传递 credential/usage context;每个搜索、详情、评论调用保留 requestId、费用和业务键
mcp/src/features/douyin-trend/live-collector.js 同上;视频、评论和翻页均写检查点并汇总实际 usage

21.5.3 Tool 和业务编排层

文件 必须修改的行为
mcp/src/tools/voc-api-catalog-run.js 删除 `endpoint.billing
mcp/src/tools/xiaohongshu-trend-run.js 删除所有分散的 buildVocRechargeInfo() 分支;使用统一预算、检查点和 recharge;部分结果也返回同一链接/二维码协议
mcp/src/tools/douyin-trend-run.js 与小红书完全同源,不再重复猜测 402/403
mcp/src/features/voc-business-workflow/business-workflow.js ok 时原样透传 recharge/usage/estimate/checkpoint/files;成功时合并各步骤实际费用,不只包装文字
mcp/src/tools/voc-business-workflow-run.js schema 和输出契约增加预算、估算、账单与续跑字段
mcp/src/features/fmode-image-analysis/image-analysis.js 使用类型化 credential;402 使用统一 NewAPI recharge,403 返回 permission;模型 usage 写同一追踪上下文
mcp/src/tools/fmode-image-analysis.js schema 注册 usage context 和统一结果字段,不泄露 Token
mcp/src/tools/voc-cost-estimate-run.js 接收 Agent 计划,筛选所需 endpoint 价目并输出三档报价;不让服务端决定调用次数
mcp/src/tools/voc-usage-report-run.js 按当前用户和追踪标识读取实际频次、quota、人民币费用和质量标识
mcp/src/server.js 注册新工具;统一 Token check;所有计费工具 schema 支持预算和上下文,但继续允许自然语言调用

21.5.4 目录、Skill 文档和发布物

文件 必须修改的行为
mcp/src/core/api-catalog.js 对外输出稳定 endpointId/channel/method/path/billingUnit/mediaFields;不输出伪价格
mcp/catalog/voc-social-endpoints.json 修正三通道认证和计费说明;为已登记接口补稳定 endpoint 元数据;去除“Session 回退扣旧额度”表述
mcp/catalog/params/*.json 仅保留参数和计费单位相关元数据,权威价格不复制到技能包
skills/voc-api-catalog/SKILL.mdskills/voc-api-catalog/references/error-codes.md 作为全包计费规则的单一说明源;统一 401/402/403、Session-to-NewAPI、Tokenized Balance 和 QR 规则
skills/xiaohongshu-trend-intelligence/*skills/douyin-trend-intelligence/* 删除旧固定 Studio/APIG 链接和旧 Session 额度描述;引用统一规则;要求部分报告保留充值及检查点
skills/voc-business-workflow/SKILL.md 要求成本预估、实际账单和充值上下文穿透业务包装
skills/fmode-image-analysis/SKILL.md 统一模型 402/403 和充值输出
skills/voc-issue-pool/SKILL.mdvoc-problem-deep-dive/SKILL.mdvoc-competitor-map/SKILL.mdvoc-content-plan/SKILL.mdvoc-speaking-script/SKILL.md 说明自身直接费用或继承上游/Agent 模型费用的规则;组成业务闭环时共享同一 usage trace,避免账单漏项
README.mddocs/payment-package-links.mddocs/live-manual-acceptance-checklist.md 更新用户流程、接口数量边界、二维码和免登录链接示例;示例只用占位 Token
.claude-plugin/plugin.jsonskill-package-manifest.jsonpackage.jsonpackage-lock.json 同步工具注册、版本和产物清单

21.6 后端逐文件修改清单

文件 必须修改的行为
fmode-server/modules/shared/newapi-metering.ts 接受统一 principal 和 resolved rule;同一事务检查用户/Token quota、幂等扣费、写 actual cost 和追踪字段
fmode-server/modules/shared/newapi-user-auth.ts 严格校验 sk-,解析真实 NewAPI 用户;补齐当前 AuthServicesk- 未验证的问题
fmode-server/modules/shared/session-newapi-principal.ts 严格校验 Session;按 Parse user id 查 NewAPI users.parse_id;必要时调用幂等同步;返回计费 principal
fmode-server/modules/shared/voc-pricing.ts 统一 endpoint 路径规范化、价格读取、版本、缓存政策和模块回退
fmode-server/modules/voc-social-api/src/routes.ts 移除新模式正常路径上的 APIGAuth.count;业务成功才调用统一 metering;接收追踪字段;返回 usage
fmode-server/modules/voc-e-commerce/src/routes.ts 与 social 路由共享 principal、价格、成功判断和扣费顺序
fmode-server/modules/voc-ecom-api/src/routes.ts 与前两者一致;保留海外 /forward 业务封装
api/api-ncloud/fmode/sync-fmode-api.js 保持 syncUser() 幂等,提供 Session 用户到 NewAPI 账户映射能力;不得在普通日志输出 Token
api/api-ncloud/fmode/newapi-user-resolution.js 继续处理 parse_id/username 冲突,增加计费身份映射测试
fmode-server/api/routes.ts + fmode-server/modules/shared/newapi-metering.ts 实现唯一新增用户计费查询接口;同一认证解析 balance、pricing、usage;强制当前 user 条件和筛选白名单。Storage 路由不由技能包调用
api/api-ncloud/fmode/routes.js 保持 /recharge/order 契约;回归 tradeNo 幂等、金额校验和 Session 身份
api/api-ncloud/fmode/serv-user.jssync-fmode-api.jscloud/user/auth-route.js 回归 AccountLog -> pay_code2 -> order_status2 -> topUpNewApiQuota;重复回调不重复到账
api/api-ncloud/profit/* 管理员看板读取新实际金额和追踪字段,同时兼容历史日志
fmode-server/api/routes.ts、三个模块构建脚本、.modules/voc-*.min.cjs 源码路由和生产构建同时包含共享认证/计费实现;无需单独的 billing .min.cjs

21.7 Studio 和 Agent runtime 修改边界

Studio 已有 /balance、Token 免登录、NewAPI 余额、支付二维码、订单轮询和到账刷新,首期不重做这些能力。需要的调整只有:

  1. Balance 页通过 billing query 增加模块、执行追踪、报告和接口用量视图。
  2. 保持 token/session -> Parse.User.become() 和消费后清理地址栏。
  3. 模型请求层拦截 Agent 自身的 402;如果本地会话身份可用,直接打开 Tokenized Balance 页或现有 Balance 弹窗。
  4. Agent 尚能回复、且是 VOC 技能中途 402 时,由 Skill 的 recharge client 返回二维码和链接。
  5. Studio 不接管 Agent 的调用计划和报价计算,也不新增任务支付模型。

由于 fmode-studio 当前本地分支存在未提交且与远端重叠的修改,编码时必须以工作树为基线增量合并,禁止用远端文件整体覆盖。

21.8 完整回归矩阵

21.8.1 身份和扣费

  • 有效 sk- 调用 social、ecommerce、overseas:只扣对应 NewAPI 账户一次。
  • 有效 Session 调用三通道:映射到同一 NewAPI 账户并扣一次,APIGAuth.count 不变。
  • sk- 401 + 有效 Session:Session 身份继续请求,仍写 NewAPI 日志。
  • 用户 NewAPI quota 不足和 Token remain quota 不足都返回 402,且不调用上游。
  • 403 用户禁用或接口权限不足返回 needs_permission,不生成充值入口。
  • 缓存命中、上游成功、业务失败、超时重试分别验证扣费次数和 cache policy。
  • 相同 requestId 重放不重复扣费;相同 id 搭配不同 endpoint/quota 返回冲突。

21.8.2 Agent 输出和充值

  • 402 + Session:assistantMessage 同时含差额、建议金额、可点击 Tokenized Balance 链接,并优先返回二维码文件或 URL。
  • Tokenized URL 只在显式 recharge.balanceUrl 和当前用户消息出现;其他字段、日志、报告、测试快照均不出现 Session。
  • 402 + 无 Session:返回 Session/登录恢复状态和检查点,不生成错误的个人 URL。
  • 缺 Token、401、403、参数错误、上游失败都不误报成余额不足。
  • /recharge/order -> pay_code2 -> order_status2 能建单、出码、轮询和到账;重复建单/回调保持幂等。
  • 支付完成后 billing query 返回新余额;当前会话从检查点续跑,已完成业务键不重采。
  • 二维码失败时仍可用 Tokenized Balance 链接;链接打开失败时仍可从已登录 Studio Balance 入口支付。

21.8.3 技能和组合工作流

  • voc_api_call 三通道均返回同一 usage/recharge 结构。
  • 小红书搜索、详情、评论任一步 402 时,完整失败和部分成功都保留正确链接、二维码、实付和检查点。
  • 抖音对应路径执行同样用例。
  • voc_business_workflow 不丢失底层 recharge/usage/estimate/checkpoint/files
  • 图片分析 402 返回 NewAPI 充值结果,403 返回 permission。
  • Token check 能区分 sk-、Session、错误类型和是否具备个人支付能力,而不回显凭证。
  • 激活流程缺 Token 时不再跳旧 APIG/workshop 充值页。
  • 所有收费 Skill 执行前通过 billing query 读取当前价目;任何 Skill 都不从 catalog billing 推导人民币价格。

21.8.4 文档、产物和安全检查

  • smoke-mcp 覆盖新工具发现、统一结果字段和业务工作流透传。
  • smoke-package 检查所有计费 Skill 引用统一规则且无旧链接。
  • 新增 credential、gateway、billing client、recharge client、Session principal、metering、二维码和续跑测试。
  • 构建 zip、npm 包和 .modules 后再次扫描明文凭证、旧固定充值入口、amount= Balance 链接和把 usageTraceId 当支付 ID 的表述。
  • 生产验收记录同一用户执行前后 NewAPI 余额、NewAPI 日志、旧 APIGAuth.count、支付到账和报告实际账单,四者必须一致。

21.9 上线依赖和门禁

新技能包不能先于 Session-to-NewAPI 后端计费能力全量发布,否则 sk- 失败后的 Session 回退仍会扣旧余额。发布顺序应为:

  1. 后端增加 unified principal、影子价格和 usage 日志,暂不改变扣费。
  2. 验证 sk- 与 Session 映射到同一用户,并对比影子金额。
  3. 灰度切换三通道到 NewAPI 统一扣费,确认旧 APIGAuth.count 不变。
  4. 上线 billing query。
  5. 发布技能包类型化凭证、统一 gateway、Agent 报价和 recharge client。
  6. 回归 Studio Tokenized Balance、二维码、支付到账和模型层 402 拦截。
  7. 最后启用通用预算保护、L1 续跑、媒体流水线和用量看板。

必须提供以下开关:

  • Session-to-NewAPI 计费灰度开关;回滚时只能切回一种计费路径,禁止双扣。
  • endpoint 价格规则开关;异常时回退模块级 NewAPI 规则。
  • Agent 二维码开关;异常时保留 Tokenized Balance URL。
  • L1 自动续跑开关;异常时保留检查点供用户继续。

21.10 本次审计后的最终判断

要保证新模式正常运行,P0 不能只做页面和一个查询接口。必须同时完成以下最小闭环:

  1. 后端 sk- 和 Session 两种身份都统一扣 NewAPI 余额。
  2. 技能包所有真实采集入口都经过同一 credential、gateway、error 和 recharge context。
  3. Agent 只调用一个新增 billing query 读取余额、价目和用量,并自行计算报价、差额和建议金额。
  4. Agent 复用现有三段支付链返回二维码,同时返回带 Session 的 /balance/?token=... 自助链接。
  5. 组合工作流和部分报告完整透传充值、账单和检查点,支付后不重复已完成调用。
  6. Studio 继续承担现有充值体验,并在 Agent 自身无法回复的模型 402 场景兜底打开充值入口。

这六项同时完成,才能满足“所有任务统一扣 NewAPI、Agent 能估价、余额不足能直接付费、充值后能继续、Balance 能看清用量”的完整业务目标。