fix(usage): centralize cache-inclusive app set and cover grokbuild in cost backfill

The cost backfill hardcoded codex|gemini as cache-inclusive apps, so
grokbuild TOTAL-semantics rows were priced on full input tokens with
cache reads double-counted. Converge the writer (proxy logger and
calculator) and the backfill recompute onto a single
sql_helpers::is_cache_inclusive_app predicate backed by the existing
CACHE_INCLUSIVE_APP_TYPES constant, and add a regression test for the
grokbuild backfill path.
This commit is contained in:
Jason
2026-07-23 16:59:41 +08:00
parent 15d5dbe065
commit 3cf84ca362
4 changed files with 63 additions and 5 deletions
+10 -1
View File
@@ -16,7 +16,16 @@
/// style provider not added here) shows up loudly as a too-low cache hit
/// rate, which is easier to catch than the silent over-deduction that
/// would happen with the opposite default.
const CACHE_INCLUSIVE_APP_TYPES: &[&str] = &["codex", "gemini", "grokbuild"];
/// 单一语义集(SSOT):写入侧(proxy logger/calculator)、回填侧
/// usage_stats 成本重算)与展示侧(本文件的 SQL 归一)都必须引用这里,
/// 防止同一语义散落多处后新增 app 时漏改(grokbuild 曾在回填侧漏掉)。
/// 前端 `src/types/usage.ts` 的同名常量是跨语言的对应物,改动须同步。
pub(crate) const CACHE_INCLUSIVE_APP_TYPES: &[&str] = &["codex", "gemini", "grokbuild"];
/// `app_type` 的存储 `input_tokens` 是否已包含 cache read/write。
pub(crate) fn is_cache_inclusive_app(app_type: &str) -> bool {
CACHE_INCLUSIVE_APP_TYPES.contains(&app_type)
}
pub(crate) const INPUT_TOKEN_SEMANTICS_LEGACY: i64 = 0;
pub(crate) const INPUT_TOKEN_SEMANTICS_TOTAL: i64 = 1;