root
b4c5f0f0fc
refactor(billing): 计费语义下沉到 Lua(内核只解 YAML/传数据)+ 采纳 PR #2 语义
按 issue #1 的修复方向(维护者评论):内核不再持有任何计费语义,billing 逻辑
全部在 `plugins/billing.lua`;内核只负责解 config.yaml、校验 schema、把
profile + 源 base_url 作为**数据**交给插件,再把插件算出的价目通过 `prices`
侧车注入。计费账目仍持久化在插件状态文件(`plugin_dir/.billing.state.json`)。
## 变更
- **删除** `internal/billing`(compile.go 359 行 + 其 Go 测试);
- 新增 `core.compileBillingPrices`:把 profile/sources JSON 化后调用插件导出
`compile_prices`,返回价目表 + 未匹配规则清单(供错误日志点名 URL);
- `applyBillingDSL` / 规则编辑器改为走同一个插件编译入口(编辑器 lenient,
半成品规则可保存、可报告);
- `billing.lua` 新增 `compile_prices`:URL 归一匹配、首条命中优先、
free/subscription/unpriced/token、USD/M→per-token、peak 窗口、
long_context 边际价、reasoning 可选价、default 策略、未匹配清单。
错误通过载荷 `error` 字段回传(插件导出第二返回值通道不可靠)。
## 与 PR #2(valuelesser)合并后的语义
- **token 规则不产生任何源条目**:未列价的模型落到 unpriced 统计(可见),
不再"静默计 $0"。比 issue 正文里的 `{per_request:0}` 标记更收口;
- `default: free` 由**编译期**给未匹配源写 `{per_request:0}` 标记;
`unpriced`/缺省不写。删除无人读取的 `default_mode` 死键;
- 保留 `unmatched_rules` 清单(只用于降级应用时点名过期 URL)。
## 判据(原 Go 单测平移到 Lua + PR #2 的用例)
- `internal/lua/billing_compile_test.go`:通配符不标记源、token 规则无源条目、
任意源条目不得携带 token 价(根因直防)、free/subscription 保留有意零价、
reasoning 缺席、long_context 三种形态、peak 形状、URL 归一+首条优先、
lenient 未匹配清单、硬错误 5 例、default 两态;
- `internal/lua/billing_test.go`:编译输出驱动真实 priceFor 的 A/B 用例
(旧形状 cost=0 / 新形状 0.75 且 unpriced=0)、default 编译期语义 e2e;
- `internal/gateway`:token 规则断言"无源条目"、模型价 per-token 量级;
- `internal/core`:过期规则 URL 降级应用(有效规则仍生效)。
2026-10-20 18:33:26 +08:00
..
2026-10-20 18:04:43 +08:00
2026-10-20 18:33:26 +08:00
2026-10-14 15:43:09 +08:00
2026-10-14 15:35:49 +08:00
2026-10-13 13:42:45 +08:00
2026-10-14 20:00:58 +08:00
2026-10-14 20:00:58 +08:00
2026-10-14 15:24:24 +08:00
2026-10-16 20:47:14 +08:00
2026-10-13 13:42:45 +08:00
2026-10-14 16:18:27 +08:00
2026-10-14 16:18:27 +08:00
2026-10-16 07:51:21 +08:00
2026-10-14 20:00:58 +08:00
2026-10-19 16:26:59 +08:00
2026-10-16 00:56:14 +08:00
2026-10-13 16:51:15 +08:00
2026-10-13 16:51:15 +08:00
2026-10-19 13:43:18 +08:00
2026-10-13 16:51:15 +08:00
2026-10-20 09:13:56 +08:00
2026-10-11 20:50:52 +08:00
2026-10-19 16:26:59 +08:00
2026-10-16 13:51:36 +08:00
2026-10-14 20:00:58 +08:00
2026-10-19 16:26:59 +08:00
2026-10-19 17:21:22 +08:00
2026-10-13 15:44:51 +08:00
2026-10-13 13:42:45 +08:00
2026-10-13 13:42:45 +08:00
2026-10-19 16:26:59 +08:00
2026-10-13 13:42:57 +08:00
2026-10-16 21:49:12 +08:00
2026-10-13 13:42:45 +08:00
2026-10-13 07:41:42 +08:00
2026-10-15 22:43:08 +08:00
2026-10-19 16:26:59 +08:00
2026-10-20 09:54:06 +08:00
2026-10-13 13:42:57 +08:00
2026-10-20 08:27:28 +08:00
2026-10-19 16:26:59 +08:00
2026-10-19 16:26:59 +08:00
2026-10-14 20:00:58 +08:00
2026-10-19 22:32:18 +08:00
2026-10-13 15:52:26 +08:00
2026-10-13 13:42:57 +08:00
2026-10-20 08:27:28 +08:00
2026-10-20 08:27:28 +08:00
2026-10-19 16:26:59 +08:00
2026-10-20 08:27:28 +08:00
2026-10-14 20:12:10 +08:00
2026-10-13 13:42:57 +08:00
2026-10-13 13:42:57 +08:00
2026-10-20 10:12:51 +08:00
2026-10-17 17:38:23 +08:00
2026-10-13 13:42:45 +08:00
2026-10-17 17:38:23 +08:00
2026-10-13 13:42:45 +08:00
2026-10-17 17:38:23 +08:00
2026-10-20 09:38:39 +08:00
2026-10-20 09:13:56 +08:00
2026-10-16 00:56:14 +08:00
2026-10-17 17:38:23 +08:00
2026-10-17 17:38:23 +08:00
2026-10-14 16:09:22 +08:00
2026-10-16 13:51:36 +08:00
2026-10-16 17:44:04 +08:00
2026-10-15 08:22:57 +08:00
2026-10-15 08:22:57 +08:00
2026-10-15 20:30:33 +08:00
2026-10-15 08:22:57 +08:00
2026-10-16 01:38:34 +08:00
2026-10-17 00:01:00 +08:00
2026-10-13 13:42:57 +08:00
2026-10-13 15:38:35 +08:00
2026-10-13 15:38:35 +08:00
2026-10-19 16:26:59 +08:00
2026-10-20 18:33:26 +08:00
2026-10-11 20:50:52 +08:00
2026-10-13 13:42:57 +08:00
2026-10-15 08:22:57 +08:00
2026-10-14 16:00:34 +08:00
2026-10-13 13:42:57 +08:00
2026-10-11 13:52:29 +08:00
2026-10-19 16:26:59 +08:00
2026-10-19 16:26:59 +08:00
2026-10-13 16:11:11 +08:00
2026-10-07 17:37:22 +08:00
2026-10-19 16:26:59 +08:00
2026-10-13 13:42:45 +08:00