Skip to content
This repository was archived by the owner on Jul 30, 2026. It is now read-only.

fix(pricing): require source-backed model prices - #77

Merged
makoMakoGo merged 3 commits into
personal/local-clientsfrom
fix/pricing-source-authority
Jun 24, 2026
Merged

fix(pricing): require source-backed model prices#77
makoMakoGo merged 3 commits into
personal/local-clientsfrom
fix/pricing-source-authority

Conversation

@makoMakoGo

@makoMakoGo makoMakoGo commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • canonicalize source-specific OpenAI route tier suffixes before pricing
  • remove private built-in prices and global pricing aliases from the resolver
  • treat explicit zero-price catalog rows as real catalog prices
  • document pricing source authority in ADR 0013

Validation

  • cargo fmt --all -- --check
  • cargo test -p tokscale-core
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo build --release -p tokscale-cli
  • target/release/tokscale pricing big-pickle --json --no-spinner
  • target/release/tokscale pricing model1 --json --no-spinner
  • target/release/tokscale pricing composer-2 --json --no-spinner
  • target/release/tokscale pricing gpt-5.3-codex --json --no-spinner

Summary by cubic

Switch pricing to source-backed catalogs and exact custom overrides only, removing built-in/private prices and global aliases. Parsers now canonicalize OpenAI reasoning-tier routes; catalog lookups accept zero-price rows, prefer original providers in models.dev, and keep cost at $0.00 when no price matches.

  • Refactors

    • Pricing uses LiteLLM, OpenRouter, and models.dev only; removed builtin pricing and alias resolver.
    • Canonicalize source-specific model IDs, including OpenAI reasoning tiers (suffix and parenthesized forms) and known “free/fast” decorations; applied in Droid and Pi parsers.
    • Catalog handling: explicit zero-price rows are valid; rows with no price fields are ignored. Provider choice favors original authors over resellers when models.dev shares a model part; anthropic/ remains canonical when tied.
    • Resolver no longer cleans route decorations; version normalization is deterministic only; tokscale pricing <model> stays a catalog query. Added ADR 0013; bumped cache schema versions.
  • Migration

    • If you rely on private or early model pricing (e.g., model1, model2, big-pickle, composer-2), add exact entries in ~/.config/tokscale/custom-pricing.json.
    • Ensure parsers emit canonical model IDs (e.g., strip -xhigh / (high) tiers); unmatched models compute as $0.00 until priced by a catalog or custom override.
    • Caches auto-refresh due to schema bumps; no manual action needed.

Written for commit 8f609b5. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • 新功能

    • 定价查询现在支持更多实时价格来源,包括 LiteLLM、OpenRouter 和 models.dev。
    • 模型名称会更智能地规范化,尤其是 OpenAI 推理档位、版本后缀和部分路径变体。
  • Bug 修复

    • 优化了模型匹配顺序,减少因别名、后缀或目录顺序导致的定价偏差。
    • 未命中定价的模型现在会保留为 $0.00,避免被错误估价。
  • 文档

    • 更新了中英文 README 和定价说明,反映最新的匹配规则、缓存来源与兜底行为。

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

本 PR 依据新建的 ADR 0013 对定价解析架构进行重构:删除全局别名映射与内置私有定价覆盖;将 OpenAI 推理档位归一化逻辑下沉至会话解析器;将"正价过滤"语义改为"可用价(含 0)过滤";未命中自定义或目录定价时成本回退 $0.00;同步递增缓存 schema 版本并更新所有相关文档与测试。

Changes

定价来源权威重构(ADR 0013)

Layer / File(s) Summary
ADR 0013 与文档更新
docs/adr/0013-pricing-source-authority.md, docs/adr/0011-token-derived-local-cost.md, docs/upstream/2026-06-22.md, README.md, README.zh-cn.md
新增 ADR 0013 全文,定义 canonical model ID 为定价与分组依据、禁止内置别名与私有覆盖、目录来源限定为 LiteLLM/OpenRouter/models.dev;更新 ADR 0011 引用与后果说明;同步英中文 README 移除 Cursor 硬编码定价与别名解析步骤,新增 models.dev 来源与 $0.00 回退描述。
OpenAI 推理档位归一化(model_aliases)
crates/tokscale-core/src/model_aliases.rs
新增 OPENAI_REASONING_TIERS 常量;用通用解析逻辑替换旧静态映射,支持括号/连字符/下划线等档位变体剥离与 base 型号校验;扩展正向与负向测试断言覆盖多种 GPT 格式。
会话解析器中的模型归一化
crates/tokscale-core/src/sessions/droid.rs, crates/tokscale-core/src/sessions/pi.rs
normalize_model_name 改为无条件调用 canonicalize_source_model_id,失败时回退原值;新增 droid gpt-* 带档位归一化测试与 pi OMP JSONL OpenAI reasoning tier 解析测试。
PricingLookup 核心重构
crates/tokscale-core/src/pricing/aliases.rs, crates/tokscale-core/src/pricing/lookup.rs, crates/tokscale-core/src/pricing/mod.rs
删除 aliases.rsresolve_alias;移除 aliases 模块导出与 build_builtin_overridesPricingLookup::new/new_with_models_dev 去掉 builtin 参数;lookup_with_source_and_provider 不再做别名解析;将"正价"过滤语义改为"可用价(含 0)";prefers_model_part_key 引入确定性优先级比较。
PricingService 测试重构
crates/tokscale-core/src/pricing/mod.rs, crates/tokscale-core/src/pricing/lookup.rs, crates/tokscale-core/tests/anthropic_catalog.rs, crates/tokscale-core/tests/fixtures/local_model_ids.txt
批量更新构造调用移除旧 builtin 参数;新增 custom_exact_key_overrides_zero_priced_catalog_modeltest_unmatched_models_cost_zero_without_builtin_prices 等用例;big-pickle 期望从 glm 定价改为 0.0/0.0
核心库与缓存版本递增
crates/tokscale-core/src/lib.rs, crates/tokscale-core/src/message_cache.rs, crates/tokscale-cli/src/tui/cache.rs
Cursor composer 测试改为断言未定价行 cost==0.0;gpt-5.3-codex 测试补充 litellm 定价表;message_cache schema 版本 31→32,TUI cache schema 版本 22→24,使旧缓存失效。

估计代码审查工作量

🎯 4 (Complex) | ⏱️ ~60 minutes

可能相关的 Issues

可能相关的 PRs

  • makoMakoGo/tokscale#69:该 PR 修改了 pricing/mod.rs 中定价服务初始化路径(添加诊断支持),与本 PR 对同一文件的 PricingLookup 构造调用改动(移除 build_builtin_overrides)存在代码级冲突风险。
  • makoMakoGo/tokscale#72:该 PR 将 UnifiedMessage.cost 计算切换到 apply_token_pricing 流水线,本 PR 更改了底层定价解析/规范化规则(别名移除、0.0 回退),两者共同决定 token 派生成本的最终值。

🐰 小兔我翻开价格的账,
别名与内置统统收场,
Canonical ID 一锤定音,
$0.00 诚实面对未知型号,
LiteLLM、OpenRouter、models.dev 三源并列,
规则清晰,缓存新版换新装!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 标题准确概括了本次 PR 的核心:将定价限制为来源驱动的模型价格,并移除内置/全局别名定价。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pricing-source-authority

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codspeed-hq

codspeed-hq Bot commented Jun 24, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 18 untouched benchmarks


Comparing fix/pricing-source-authority (8f609b5) with personal/local-clients (effda9c)

Open in CodSpeed

@makoMakoGo
makoMakoGo marked this pull request as ready for review June 24, 2026 10:29

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 16 files

Re-trigger cubic

@makoMakoGo
makoMakoGo force-pushed the fix/pricing-source-authority branch from 4f572cd to b49be7c Compare June 24, 2026 11:55

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/tokscale-core/src/model_aliases.rs`:
- Around line 52-58: The model alias normalization in model_aliases.rs only
handles hyphen-separated tiers, so `_tier` variants like gpt-5.5_xhigh are not
being mapped to the base model and can miss pricing. Update the normalization
logic in the alias parsing path around the existing rsplit_once('-') handling to
also recognize underscore tier suffixes (and preserve the current
fast/reasoning-tier checks in is_openai_gpt_source_base_model /
OPENAI_REASONING_TIERS), then add tests covering underscore-based aliases such
as gpt-5.5_xhigh and gpt-5.4-mini_xhigh to ensure they resolve to the base model
for pricing lookup.

In `@README.md`:
- Line 409: The “Exact Match” source list is inconsistent with other
documentation references and should be updated to include models.dev alongside
LiteLLM/OpenRouter. Edit the README section containing the Exact Match
description so it matches the existing mentions in the document and keeps the
query strategy wording consistent across the README.

In `@README.zh-cn.md`:
- Line 378: The query strategy description for “精确匹配” is inconsistent with the
broader source list because it only mentions LiteLLM/OpenRouter and omits
models.dev. Update the wording in the README.zh-cn section that describes this
strategy so it matches the three-source declaration used elsewhere, keeping the
text aligned with the symbols and terminology around the query strategy list and
source coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: af519999-2cb4-4f0c-bfb4-2f65d295fa2d

📥 Commits

Reviewing files that changed from the base of the PR and between effda9c and b49be7c.

📒 Files selected for processing (16)
  • README.md
  • README.zh-cn.md
  • crates/tokscale-cli/src/tui/cache.rs
  • crates/tokscale-core/src/lib.rs
  • crates/tokscale-core/src/message_cache.rs
  • crates/tokscale-core/src/model_aliases.rs
  • crates/tokscale-core/src/pricing/aliases.rs
  • crates/tokscale-core/src/pricing/lookup.rs
  • crates/tokscale-core/src/pricing/mod.rs
  • crates/tokscale-core/src/sessions/droid.rs
  • crates/tokscale-core/src/sessions/pi.rs
  • crates/tokscale-core/tests/anthropic_catalog.rs
  • crates/tokscale-core/tests/fixtures/local_model_ids.txt
  • docs/adr/0011-token-derived-local-cost.md
  • docs/adr/0013-pricing-source-authority.md
  • docs/upstream/2026-06-22.md
💤 Files with no reviewable changes (1)
  • crates/tokscale-core/src/pricing/aliases.rs

Comment on lines +52 to +58
if let Some((base, tier)) = model.rsplit_once('-') {
if (tier == "fast" || OPENAI_REASONING_TIERS.contains(&tier))
&& is_openai_gpt_source_base_model(base)
{
return Some(base.to_string());
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

补上 _tier 后缀解析,否则下划线档位会漏定价。

当前只按 - 拆分,gpt-5.5_xhigh / gpt-5.4-mini_xhigh 这类下划线 tier 不会规范化,后续 pricing lookup 会按未命中回退 $0.00。PR 目标提到支持下划线变体,建议同时补测试覆盖。

建议修复
-    if let Some((base, tier)) = model.rsplit_once('-') {
-        if (tier == "fast" || OPENAI_REASONING_TIERS.contains(&tier))
-            && is_openai_gpt_source_base_model(base)
-        {
-            return Some(base.to_string());
-        }
+    for separator in ['-', '_'] {
+        if let Some((base, tier)) = model.rsplit_once(separator) {
+            if (tier == "fast" || OPENAI_REASONING_TIERS.contains(&tier))
+                && is_openai_gpt_source_base_model(base)
+            {
+                return Some(base.to_string());
+            }
+        }
     }

Also applies to: 316-330

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/tokscale-core/src/model_aliases.rs` around lines 52 - 58, The model
alias normalization in model_aliases.rs only handles hyphen-separated tiers, so
`_tier` variants like gpt-5.5_xhigh are not being mapped to the base model and
can miss pricing. Update the normalization logic in the alias parsing path
around the existing rsplit_once('-') handling to also recognize underscore tier
suffixes (and preserve the current fast/reasoning-tier checks in
is_openai_gpt_source_base_model / OPENAI_REASONING_TIERS), then add tests
covering underscore-based aliases such as gpt-5.5_xhigh and gpt-5.4-mini_xhigh
to ensure they resolve to the base model for pricing lookup.

Comment thread README.md
Comment thread README.zh-cn.md
@@ -376,13 +376,11 @@ tokscale pricing "claude-3-5-sonnet" --provider litellm

1. **自定义价格覆盖** - `~/.config/tokscale/custom-pricing.json` 中大小写不敏感的完整 key 精确匹配
2. **精确匹配** - 在 LiteLLM/OpenRouter 数据库中直接查找

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

查询策略中的“精确匹配”来源缺少 models.dev。

Line 378 仅提到 LiteLLM/OpenRouter,但 Line 1325 已声明三源(含 models.dev)。建议保持一致,避免中文读者误解查询覆盖范围。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.zh-cn.md` at line 378, The query strategy description for “精确匹配” is
inconsistent with the broader source list because it only mentions
LiteLLM/OpenRouter and omits models.dev. Update the wording in the README.zh-cn
section that describes this strategy so it matches the three-source declaration
used elsewhere, keeping the text aligned with the symbols and terminology around
the query strategy list and source coverage.

@makoMakoGo
makoMakoGo force-pushed the fix/pricing-source-authority branch from b49be7c to 8f609b5 Compare June 24, 2026 12:25
@makoMakoGo
makoMakoGo merged commit 812c926 into personal/local-clients Jun 24, 2026
8 checks passed
@makoMakoGo
makoMakoGo deleted the fix/pricing-source-authority branch June 24, 2026 12:38
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant