Skip to content

运行与模型消费回执(#1470) ​

对外合同 ​

新 OAuth scope billing:receipts 仅允许 GET /api/billing/v1/receipts 和 GET /api/billing/v1/summary。现有 token、billing:read、web:receipts 不自动扩权;JWT/API Key/agent 也只能读取本次已验证身份范围。OAuth 同一用户与 app 的新 token 可查旧回执,另一 app/用户不可查。调用方不能传 team/user/app 改付款或查询范围。

JWT 只查询当前用户的已验证来源;API Key / agent 凭据还必须显式获授 Usage Receipts 权限组,能调用模型不等于能读取账证。缺少路由权限返回 403;已获权限但查询其它来源的回执返回 404。OAuth 必须有 billing:receipts,不能用桥接付款 Key 扩大原 OAuth caller 的查询范围。

模型、ASR、API/Release run 返回 X-Wainao-Request-Id;新 editor run 的 runId 同时是 requestId。模型、ASR、API/Release run 和新 run 客户端可在第一次调用带 Idempotency-Key(最多 200 字符);body requestId(最多 128 字符)仍仅对 OAuth 有幂等语义;其它身份的 body requestId 仍为审计元数据,新增幂等必须显式使用 header。匿名赞助 Release 不提供共享配置 Key 的客户端幂等定位。运行创建请求的例外:同一已验证身份、键和客户端请求内容的新版本已受理 run 返回 200 { runId, status, idempotentReplay: true },不重执行、不重复扣费;同键语义不同或旧 run 缺少可核验请求指纹时返回 409 idempotency_conflict,不重新执行。普通模型、ASR 的同来源/键/绑定重放返回 409 与原 request 引用;图片/TTS另按下述媒体恢复合同处理,已经存储且可交付的原结果可返回200,并带 X-Wainao-Idempotent-Replay。旧 editor 三路径只提供服务端 requestId,不支持客户端幂等键。旧 API run 的 app+request_id 唯一索引仍保留,不同用户同 app 碰撞也只返回冲突,不泄漏旧 run。

  • GET /api/billing/v1/receipts?requestId=... 或 clientRequestId=...,二选一。最多 100 个事件;沿用响应的 asOf 与 nextCursor 作为下页 after。水位只冻结事件创建范围,各事件的结算状态可以更新,以 revision 为准。
  • GET /api/billing/v1/summary?since=ISO&before=ISO,默认最近 30 天,最多 366 天;数据库聚合整个范围,不从单页回执累加。
  • 金额统一 milli-credit 整数字符串,1000 milli-credit = 1 积分。walletDebitedMilliCredits 为实际钱包扣减,refundedMilliCredits 为退款,净额独立返回。原应计、权益减免不能与钱包扣减相加。
  • origin/run 已提交但固定费受理失败返回 503 run_acceptance_incomplete 与 requestId,并尽力将 run 标记 error;数据库不可用时状态可能待恢复,应查询引用。运行创建的 200 idempotentReplay 只表示已找到原 run,不能把它当作执行成功;其它操作的 409 已有引用也不代表执行成功。缺失/跨身份回执统一 404;数据库不可用 503;未知计量、缺价、待结算分别显示,不以空数组或零汇总宣称“免费”。响应禁止缓存。

覆盖范围 ​

coverage=new_verified_events_only 仅代表以下新版本落库的事件,不能当作全历史账单或全部工具成本:

写入口本批行为
AIService 直连供应商(含工作流 generation/structure/prompt-condition/builtin)每次真实 attempt 先持久 intent;成功持久计量后结算;移除同位置旧异步扣费
Model Gateway chat / ASR 两协议分支验证原始 caller,桥接付款 Key 单独保存;冻结报价、权益与来源;回执关联
API/Release run 六响应路径、editor 三旧路径、新 run/worker/inlineorigin+run 同事务;固定费保留旧幂等键;插入失败不执行;恢复校验 seal 并消费同一验证行的输入快照
Ask/resume原来源与付款方不改;记录当次 resumer/executor;不能用 runs 可修改列重建身份
历史/滚动升级 run仅受保护 registry 放行;未来模型事件注明 legacy_unverified,无公开可信回执,不回填历史固定费
Peer relay保留远端收费,当前节点不重复扣费;本地 runtime 回执不覆盖远端明细
Native、Gateway/KB embedding、Graphiti当前源码已有持久来源、冻结报价和 attempt;分别沿用原计量及权限,不回填旧调用
新 Gateway video已有任务预留、event 与交付状态机;预留不等于最终扣款,保留 reservation 字段
Gateway rerank(#1645)外呼前持久来源及 attempt;保留 searchUnits 用量、冻结价格,取消或故障只恢复原账证
Gateway图片/TTS(#1645)外呼前冻结来源、价据和媒体event;成功量先持久化,文件可交付后才能结算;恢复不重生成
PDF、旧 workflow/video runner、媒体历史未绑定记录、无 billing context 内部探针未纳入当前 runtime 完整性保证,不能因新增目录而宣称已覆盖
web.search/fetch已发布的 /api/web/v1/receipts 与 web:receipts,不混入 runtime summary

可靠性与恢复 ​

actor、payer、executor 分开,payer 是实际团队所有者快照;项目转移不改已接受 run 的付款主体。新 origin 与 run 绑定 hash 覆盖 inputs/envelope 内容;worker/inline 使用私有 RPC 返回的同一已验证行快照,拒绝客户端伪造、篡改及无 registry 的旧来源。

报价包含规则、工具价格、兑换率、权益决策时间;数据库读取失败阻止供应商调用。模型未知和缺价不猜零,不用后来的价格补扣。run 固定费成功查库确认未配置规则时沿用既有免费策略,快照明确 runFeePolicy=unconfigured_free,记录已结算零扣减;数据库查询失败不适用此策略。begin 数据库重试沿用本进程生成的 event UUID;数据库恢复没有重新调用供应商的执行权。complete/settle 写失败不触发 provider fallback;旧 worker 已先用兼容 key 扣款但无法还原分桶时标记 legacy_settlement_collision 待人工对账,不重复扣款、猜退款或无限异常重试。已知金额由 5 分钟 cron 安全重试,未知超过 15 分钟进入人工对账。真实供应商 fallback 是新的 attempt,分别保留证据。

管理员 /admin/billing/service-usage-pending?kind=runtime 查看未知、缺价、结算失败与跨期退款待对账;余额不足单独按 24 小时阈值告警,充值后仍可结算。原桶退款、幂等退款键、上限与周期检查由 service-role RPC 执行;不提供插件任意退款接口。

验证与发布 ​

前置数据库 #1476/#1477/#1479 先合入并经唯一 apply/verify;再部署 backend 与 worker。真实 PostgreSQL 测试覆盖权限、并发单扣、分桶退款、跨期、seal、token 轮换、统计与回滚键。服务故障测试使用真实 AI/ASR 服务 + 账证编排,供应商/数据库故障替身;不能替代线上实际供应商验收。浏览器、Host 展示与 SDK 联调需独立记录。

回滚只回应用镜像,保留金融事实与恢复 cron;不得删事件或重发供应商补账。开发者自由定价与分账不在本批范围。

#1645 请求目录 ​

无需本机 requestId 的查询见 消费请求目录。旧 /summary 使用事件创建时间;新目录及其汇总使用请求创建时间,不应直接比较二者的窗口总额。新路由使用独立权限,不能给旧 token 自动扩权。

#1645 媒体交付与执行者分段 ​

图片/TTS的新请求即使不带幂等键,也先在同一数据库事务内保存origin、媒体event、交付意图和冻结报价,再调用一次供应商。只保存成功用量不立即扣钱:私有结算函数验证原request/project/user/team及精确文件,续租后按原model:<request>:<executionPath>账本键结算,保留Storage发布guard和滚动版本兼容。新媒体已落来源的claim不允许旧后端删除后再次生成,旧直扣也必须通过媒体事务授权。

文件缺失、无法交付或余额不足期间保持pending;至原媒体意图创建后一小时仍未交付则转待对账;既有平台承担任务还要求至少10分钟静默窗,之后收口未扣费用,不能在终态后迟到补扣。此期限是媒体专用规则,与普通模型24小时余额告警不同。平台承担和应计零额都不构成文件交付成功;正价订阅特权允许钱包0、但仍需有效应计账证和文件绑定。

新的X-Wainao-Billing-State与X-Wainao-Request-Id在可恢复错误中保留。已stored文件按冻结价格恢复,已扣款但发布失败只恢复发布;旧TTS无冻结价、又无精确原流水时转对账,不按今日价格追扣。旧图片已有冻结价的兼容路径仍受原文件和流水校验。

Ask/resume给每段执行分配冻结的executorSegmentNo。异步子流保留开始时的段号,即使父run随后被其他人恢复,也不按最新执行者错记;固定run费仍属于原发起段0。兼容旧backend时仅允许唯一匹配的已封存执行者快照,歧义拒绝,不能猜测最新段。

故障边界:上传完成后若claim的stored状态写入失败,保留成功应计及私有文件但不绑定结算,也不重新生成;到交付期限转平台承担。此窗口尚无自动恢复文件交付能力,不能把供应成功当客户端交付成功。先保住无重复扣费和可对账事实,不宣称所有故障都能恢复音频/图片。

媒体尚在处理、或已有来源但不能重新领取外呼资格时,重复键返回409 request_already_accepted(TTS亦可能为 idempotency_in_progress)和原请求引用;已存储/完成且可恢复原文件时返回200 replay。恢复结算或交付暂不可用、包括余额不足时返回503,可用原requestId补查;进入reconciliation、unpriced、平台承担或明确不可交付后返回固定 409 media_delivery_unavailable,不再暗示重复调用可以完成交付,后续按账证处理。恢复图片或语音前重新核验身份与交付状态,终态不得通过已有Storage文件直接发布。OAuth的幂等来源范围为同一用户+同一App;跨Team复用同键会因付款主体不同返回409,客户端应使用新键表示新的消费请求。

媒体受理响应丢失时,只有持有本进程原requestId和eventId、且数据库仍为一小时期限内的pending/unknown无执行证据及未绑定文件,才能恢复本次外呼资格;其他进程只能查询账证。只有来源而缺媒体意图的历史异常返回 409 media_admission_incomplete 和已核验的requestId,不能改键重生成来修复账证。一小时从受理时间计算,排队时间也计入。

媒体受理重放仍须当前身份有效;撤销或被新版本取代的token不能借旧幂等键恢复外呼。查旧账证应使用重新授权且具备查询权限的有效token:同一user+App用来源回执接口,官方Host或JWT可按本人权限使用 /me/receipts。

AI Workflow Editor