fix(core): retain usage without provider attribution - #164
Conversation
|
Warning Review limit reached
Next review available in: 16 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (17)
Walkthrough该 PR 统一了 provider attribution 处理:有效模型与 token 记录在 provider 缺失或推断失败时继续保留,并以规范化 provider 或 ChangesProvider attribution 与会话解析
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant ClientSource
participant SessionParser
participant ProviderIdentity
participant UnifiedMessage
ClientSource->>SessionParser: usage record with model and optional provider
SessionParser->>ProviderIdentity: source_provider_id(raw provider, model)
ProviderIdentity-->>SessionParser: explicit provider, inferred provider, or unknown
SessionParser->>UnifiedMessage: retain tokens and attach provider_id
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
crates/tokscale-core/src/sessions/opencode.rs (1)
228-233: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win保留已发布的 provider 语义错误变体。
从公共枚举移除
MissingProviderId和EmptyProviderId会使引用这些变体的下游代码无法编译。它们可以停止产生,但应继续保留并标记弃用,除非本次发布明确包含破坏性 API 版本升级。建议修改
pub enum OpenCodeMessageSemanticError { #[error("modelID is missing or null")] MissingModelId, #[error("modelID must not be empty or whitespace")] EmptyModelId, + #[deprecated(note = "provider attribution is now optional")] + #[error("providerID is missing or null")] + MissingProviderId, + #[deprecated(note = "provider attribution is now optional")] + #[error("providerID must not be empty or whitespace")] + EmptyProviderId,🤖 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/sessions/opencode.rs` around lines 228 - 233, 在 OpenCodeMessageSemanticError 公共枚举中保留 MissingProviderId 和 EmptyProviderId 变体,不要删除它们;为这两个已停止产生的变体添加弃用标记,并保持现有 modelID 相关变体不变,以兼容引用旧 API 的下游代码。crates/tokscale-core/src/sessions/kilo.rs (1)
226-232: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win请始终通过中央解析器处理显式
providerID。当前分支会原样保留
"unknown"或"<provider>"等非空占位值,导致已知模型无法回推真实 provider。请将原始值直接传给source_provider_id。建议修改
- let provider = msg - .provider_id - .as_deref() - .map(str::trim) - .filter(|provider| !provider.is_empty()) - .map(str::to_string) - .unwrap_or_else(|| provider_identity::source_provider_id("", &model_id)); + let provider = provider_identity::source_provider_id( + msg.provider_id.as_deref().unwrap_or_default(), + &model_id, + );As per coding guidelines,provider attribution 应集中推断,并在推断失败时使用
unknown。🤖 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/sessions/kilo.rs` around lines 226 - 232, Update the provider resolution in the session handling flow to always pass the raw optional provider_id value through provider_identity::source_provider_id, rather than preserving non-empty placeholders such as "unknown" or "<provider>". Keep the centralized resolver responsible for attribution and its existing unknown fallback behavior.Source: Coding guidelines
🧹 Nitpick comments (1)
crates/tokscale-core/src/adapters/file.rs (1)
552-579: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win补充“配置从缺失变为存在”的缓存失效回归。
当前测试只证明缺失配置时可以写缓存,未验证随后创建
config.toml会触发 miss。该路径若回归,会持续返回缓存中的active-model/unknown,忽略新配置的模型和 provider。建议补充的断言
assert_eq!(messages[0].model_id.as_ref(), "active-model"); + assert_eq!(messages[0].provider_id.as_ref(), "unknown"); assert_eq!(messages[0].tokens.input, 10); assert_eq!(messages[0].tokens.output, 2); assert!(cache .get_meta(&wire_path, KIMI_ADAPTER.parser_version) .unwrap() .is_some()); + + write_file( + &config_path, + r#"[models.active-model] +provider = "openai" +model = "gpt-5" +"#, + ); + let changed_unit = KIMI_ADAPTER.discover_checked(&ctx).unwrap().pop().unwrap(); + let crate::adapters::CacheHitPlan::Miss(changed_unit) = + KIMI_ADAPTER.plan_cache_hit(changed_unit, &cache).unwrap() + else { + panic!("new Kimi config must invalidate the absent-dependency cache"); + }; + let changed_messages = + fold_with_adapter(&KIMI_ADAPTER, vec![changed_unit], &mut cache); + assert_eq!(changed_messages[0].model_id.as_ref(), "gpt-5"); + assert_eq!(changed_messages[0].provider_id.as_ref(), "openai");🤖 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/adapters/file.rs` around lines 552 - 579, Extend kimi_missing_config_keeps_usage_and_caches_the_absent_dependency to create config.toml after the initial scan/cache write, then scan and fold the same wire data again with the existing cache. Assert the dependency change causes a cache miss and the resulting message uses the configured model and provider instead of the previously cached active-model/unknown values.
🤖 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/sessions/kimi.rs`:
- Around line 301-323: 在解析 alias 映射并插入 aliases 的逻辑中,不要将 provider 视为必填字段;只要 model
非空就保留 ModelIdentity。复用中央 provider 推断逻辑为可选 provider 赋值,推断失败时使用 unknown,避免 opaque
alias 被当作模型 ID。同步更新相关测试,使 alias 使用 opaque 名称并覆盖缺失 provider 的映射与分组定价行为。
In `@docs/clients.md`:
- Around line 119-123: 明确 Kimi Code 的关联规则:preceding llm.request 必须限定为同一 alias
的最近一个有效前置请求。更新该段文档,说明不得使用任意其他 alias 的请求或后续请求回填更早的 usage,并保持 alias 按 agent wire
顺序解析的契约。
---
Outside diff comments:
In `@crates/tokscale-core/src/sessions/kilo.rs`:
- Around line 226-232: Update the provider resolution in the session handling
flow to always pass the raw optional provider_id value through
provider_identity::source_provider_id, rather than preserving non-empty
placeholders such as "unknown" or "<provider>". Keep the centralized resolver
responsible for attribution and its existing unknown fallback behavior.
In `@crates/tokscale-core/src/sessions/opencode.rs`:
- Around line 228-233: 在 OpenCodeMessageSemanticError 公共枚举中保留 MissingProviderId
和 EmptyProviderId 变体,不要删除它们;为这两个已停止产生的变体添加弃用标记,并保持现有 modelID 相关变体不变,以兼容引用旧 API
的下游代码。
---
Nitpick comments:
In `@crates/tokscale-core/src/adapters/file.rs`:
- Around line 552-579: Extend
kimi_missing_config_keeps_usage_and_caches_the_absent_dependency to create
config.toml after the initial scan/cache write, then scan and fold the same wire
data again with the existing cache. Assert the dependency change causes a cache
miss and the resulting message uses the configured model and provider instead of
the previously cached active-model/unknown values.
🪄 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: e12a1ca5-d9c1-4669-a287-ad3ad892b7c7
📒 Files selected for processing (52)
AGENTS.mdCONTEXT.mdcrates/tokscale-core/src/adapters/antigravity.rscrates/tokscale-core/src/adapters/codebuddy.rscrates/tokscale-core/src/adapters/codebuff.rscrates/tokscale-core/src/adapters/file.rscrates/tokscale-core/src/adapters/goose.rscrates/tokscale-core/src/adapters/hermes.rscrates/tokscale-core/src/adapters/junie.rscrates/tokscale-core/src/adapters/kilo.rscrates/tokscale-core/src/adapters/mod.rscrates/tokscale-core/src/adapters/omp.rscrates/tokscale-core/src/adapters/openclaw.rscrates/tokscale-core/src/adapters/pi.rscrates/tokscale-core/src/adapters/vscode_tasks.rscrates/tokscale-core/src/adapters/warp.rscrates/tokscale-core/src/provider_identity.rscrates/tokscale-core/src/scanner.rscrates/tokscale-core/src/sessions/amp.rscrates/tokscale-core/src/sessions/antigravity_cli.rscrates/tokscale-core/src/sessions/codebuddy.rscrates/tokscale-core/src/sessions/codebuff.rscrates/tokscale-core/src/sessions/commandcode.rscrates/tokscale-core/src/sessions/copilot.rscrates/tokscale-core/src/sessions/droid.rscrates/tokscale-core/src/sessions/goose.rscrates/tokscale-core/src/sessions/hermes.rscrates/tokscale-core/src/sessions/junie.rscrates/tokscale-core/src/sessions/kilo.rscrates/tokscale-core/src/sessions/kimi.rscrates/tokscale-core/src/sessions/mux.rscrates/tokscale-core/src/sessions/openclaw.rscrates/tokscale-core/src/sessions/opencode.rscrates/tokscale-core/src/sessions/pi.rscrates/tokscale-core/src/sessions/roocode.rscrates/tokscale-core/src/sessions/warp.rscrates/tokscale-core/src/sessions/zed.rscrates/tokscale-core/src/source_health.rsdocs/adr/0001-no-silent-fallback.mddocs/adr/0008-single-copy-memory-pipeline.mddocs/adr/0011-token-derived-local-cost.mddocs/adr/0013-pricing-source-authority.mddocs/adr/0019-current-format-only-local-storage.mddocs/adr/0020-strict-source-identity-and-error-contract.mddocs/adr/0021-isolated-source-failure-domains.mddocs/adr/0022-deterministic-cli-command-semantics.mddocs/cli.mddocs/clients.mddocs/facts/kimi-code.mddocs/pricing.mddocs/upstream/2026-06-22.mddocs/upstream/2026-07-10.md
💤 Files with no reviewable changes (2)
- docs/adr/0011-token-derived-local-cost.md
- docs/adr/0021-isolated-source-failure-domains.md
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 04544b4855
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Represent unavailable optional related inputs in source snapshots so inventory preparation and refresh retain the primary source. Force a partial uncached scan and invalidate stale shards, while required and primary input failures remain unavailable.
背景
部分本地 session parser 把 provider 归属当成 usage 合法性的前置条件:即使记录已经包含非空 model、有效时间戳和完整 token,只要 provider 缺失或模型族推断失败,usage 仍可能被丢弃。provider 只是归属与分组元数据,不应覆盖 model 和 token 事实。
Kimi Code 进一步暴露了这个问题:
usage.record保存 model alias;较新的 per-agent wire 会在前序llm.request中记录物理 model、alias 和传输协议,而当前config.toml既可变也不是历史快照。改动
unknown;provider 失败不再丢弃有效 model/token。llm.request.model,无请求证据时才尝试当前 config 的精确映射,最后保留 raw alias。llm.request.provider仅视为传输协议,不作为模型所有者;重试请求不会重复生成 usage,未来请求也不会回填更早记录。docs/facts/kimi-code.md,记录已核验的当前存储布局、wire shape、请求与 usage 因果关系及真实语料快照。影响
能够确定 model 和 token 的 usage 会稳定进入聚合;provider 推断或
unknown属于成功归一化,不会污染 source health。缺失 model、无效时间戳、非法 token、来源不可读或真正缺少 ownership 证据仍会按原有完整性合同显示。验证
cargo test --workspacecargo clippy --workspace --all-targets -- -D warningscargo fmt --all -- --checkgit diff --checkbun run build:coreSummary by CodeRabbit
新功能
unknown。Bug 修复
文档