From 820cc701e11daba60602ee350a647d988d8afe94 Mon Sep 17 00:00:00 2001 From: ItsJazii <144446489+ItsJazii@users.noreply.github.com> Date: Wed, 12 Aug 2026 21:43:27 +0500 Subject: [PATCH 1/3] Bake in Grok 4.6 launch pricing until catalogs catch up Released today (2026-08-12); no public catalog carries it yet, so Grok 4.6 spend showed the unpriced warning. Rates from docs.x.ai/docs/pricing: $2 in / $0.50 cached / $6 out per MTok, doubling for >=200k-prompt requests (whole-request tiering, matching request_cost at the default 200k threshold); cache writes bill as plain input. The 2x fast variant resolves through the existing -fast multiplier path. Catalog entries outrank this the moment one ships. Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 9 +++++++++ src-tauri/src/pricing.rs | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 016a9073..e362660c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## Unreleased + +### Fixed +- **Grok 4.6 prices from day one** — xAI's launch-day rates + ($2 in / $0.50 cached / $6 out per MTok, doubling for ≥200k-token + prompts; the fast variant at 2x) are baked in until the public + catalogs learn the model, so spend from Grok 4.6 sessions shows + dollars instead of the unpriced ⚠. + ## 0.4.33 — 2026-08-12 ### Fixed diff --git a/src-tauri/src/pricing.rs b/src-tauri/src/pricing.rs index e055a9de..3c487931 100644 --- a/src-tauri/src/pricing.rs +++ b/src-tauri/src/pricing.rs @@ -668,6 +668,7 @@ fn builtin_price(canonical: &str) -> Option { let bare = canonical .strip_prefix("moonshot/") .or_else(|| canonical.strip_prefix("moonshot-ai/")) + .or_else(|| canonical.strip_prefix("xai/")) .unwrap_or(canonical); match bare { "kimi-k3" | "kimi-k3-code" => Some(Price::flat(3.0, 15.0, 0.3, 3.0)), @@ -675,6 +676,21 @@ fn builtin_price(canonical: &str) -> Option { // output $6, implicit cache read $0.25, explicit cache write $2.50. // Public catalogs still carry 0/0 placeholders for these slugs. "qwen3.8-max" | "qwen3.8-max-preview" => Some(Price::flat(2.0, 6.0, 0.25, 2.5)), + // Grok 4.6, released 2026-08-12 — docs.x.ai/docs/pricing (USD/MTok): + // $2 in / $0.50 cached / $6 out; prompts ≥200k bill $4 / $1 / $12 + // for the WHOLE request (xAI's long-context rule matches + // request_cost's tiering, and Grok spend passes the default 200k + // threshold). xAI bills no separate cache-write rate — writes are + // plain input. The announced 2x "-fast" variant needs no entry: + // the -fast resolution path applies the default 2x multiplier to + // this rate card. Public catalogs don't carry 4.6 yet. + "grok-4.6" | "grok-4-6" => Some(Price { + input_200k: Some(4.0), + output_200k: Some(12.0), + cache_read_200k: Some(1.0), + cache_write_200k: Some(4.0), + ..Price::flat(2.0, 6.0, 0.5, 2.0) + }), _ => None, } } @@ -768,6 +784,29 @@ mod tests { assert_eq!((terra.input, terra.output), (1.75, 11.0)); } + #[test] + fn grok_46_builtin_prices_with_long_context_tier() { + // Vendor rates (docs.x.ai/docs/pricing): $2/$0.50/$6, doubling for + // ≥200k prompts — resolvable in every spelling before the public + // catalogs learn the model. Empty store = builtin only. + let store = super::Store::default(); + for slug in ["grok-4.6", "grok-4-6", "xai/grok-4.6", "grok-4.6-high"] { + let p = super::resolve(&store, slug, 0) + .unwrap_or_else(|| panic!("{slug} did not price")); + assert_eq!((p.input, p.output, p.cache_read, p.cache_write), (2.0, 6.0, 0.5, 2.0), "{slug}"); + assert_eq!( + (p.input_200k, p.output_200k, p.cache_read_200k), + (Some(4.0), Some(12.0), Some(1.0)), + "{slug}" + ); + } + // The fast variant is "twice the price" (launch post): the -fast + // path scales the whole rate card, long-context tier included. + let fast = super::resolve(&store, "grok-4.6-fast", 0).unwrap(); + assert_eq!((fast.input, fast.output, fast.cache_read), (4.0, 12.0, 1.0)); + assert_eq!(fast.input_200k, Some(8.0)); + } + #[test] fn kimi_k3_builtin_prices_every_spelling() { // Vendor-documented rates (platform.kimi.ai): $3 in, $15 out, $0.30 From 119725b4361b0c8aa883b0ad1ee29801cb75d58e Mon Sep 17 00:00:00 2001 From: ItsJazii <144446489+ItsJazii@users.noreply.github.com> Date: Thu, 13 Aug 2026 15:05:30 +0500 Subject: [PATCH 2/3] Cursor-prefixed slugs, fast-tier backstop, corrections rev for Grok 4.6 - builtin_price strips Cursor''s "cursor-" branding: the CSV logs cursor-grok-4.6-xhigh, which showed $0.00 for 20.6M real tokens until it resolved to the baked rate card. - grok_price backstop: 4.6''s "fast" is a 2x premium tier (launch post), never the old cheap grok-4-fast branch. - CORRECTIONS_REV bump so persisted spend re-prices under the new baked entry. Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 3 ++- src-tauri/src/pricing.rs | 13 +++++++++++-- src-tauri/src/spend.rs | 13 ++++++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e362660c..2f2ec7ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ ($2 in / $0.50 cached / $6 out per MTok, doubling for ≥200k-token prompts; the fast variant at 2x) are baked in until the public catalogs learn the model, so spend from Grok 4.6 sessions shows - dollars instead of the unpriced ⚠. + dollars instead of the unpriced ⚠ — including Cursor sessions, whose + usage export brands the model `cursor-grok-4.6-xhigh`. ## 0.4.33 — 2026-08-12 diff --git a/src-tauri/src/pricing.rs b/src-tauri/src/pricing.rs index 3c487931..570c585b 100644 --- a/src-tauri/src/pricing.rs +++ b/src-tauri/src/pricing.rs @@ -166,7 +166,7 @@ pub fn generation() -> u64 { /// fingerprinted below — an app update that reprices the same files would /// otherwise leave history at the old dollars until upstream happens to /// rewrite a catalog. -const CORRECTIONS_REV: u32 = 3; // 3: zero-rate catalog placeholders no longer price at $0.00 +const CORRECTIONS_REV: u32 = 4; // 4: grok-4.6 builtin launch pricing /// Stable fingerprint of the effective pricing inputs: the on-disk catalog /// files plus this binary's corrections revision. The persistent spend @@ -669,6 +669,11 @@ fn builtin_price(canonical: &str) -> Option { .strip_prefix("moonshot/") .or_else(|| canonical.strip_prefix("moonshot-ai/")) .or_else(|| canonical.strip_prefix("xai/")) + // Cursor's CSV brands third-party slugs ("cursor-grok-4.6-xhigh"); + // the supplement's alias rules normally translate these, but a + // launch-day model needs the baked rates before the supplement + // learns the new slug. + .or_else(|| canonical.strip_prefix("cursor-")) .unwrap_or(canonical); match bare { "kimi-k3" | "kimi-k3-code" => Some(Price::flat(3.0, 15.0, 0.3, 3.0)), @@ -790,7 +795,11 @@ mod tests { // ≥200k prompts — resolvable in every spelling before the public // catalogs learn the model. Empty store = builtin only. let store = super::Store::default(); - for slug in ["grok-4.6", "grok-4-6", "xai/grok-4.6", "grok-4.6-high"] { + // cursor-grok-4.6-xhigh is the exact slug Cursor's CSV logged on + // launch day — 20.6M real tokens showed $0.00 until it resolved. + for slug in + ["grok-4.6", "grok-4-6", "xai/grok-4.6", "grok-4.6-high", "cursor-grok-4.6-xhigh"] + { let p = super::resolve(&store, slug, 0) .unwrap_or_else(|| panic!("{slug} did not price")); assert_eq!((p.input, p.output, p.cache_read, p.cache_write), (2.0, 6.0, 0.5, 2.0), "{slug}"); diff --git a/src-tauri/src/spend.rs b/src-tauri/src/spend.rs index b0288ef1..ae1334ae 100644 --- a/src-tauri/src/spend.rs +++ b/src-tauri/src/spend.rs @@ -413,7 +413,18 @@ fn codex_price(model: &str) -> (f64, f64, f64) { fn grok_price(model: &str) -> (f64, f64) { let m = model.to_lowercase(); - if m.contains("code") || m.contains("fast") { + // Grok 4.6's "fast" is a 2x PREMIUM speed tier (launch post: "twice + // the price"), the opposite of the older grok-4-fast/grok-code-fast + // line where "fast" meant a smaller, cheaper model — 4.6 slugs must + // never fall into that cheap branch. (Normally unreachable: the + // baked-in catalog entry resolves 4.6 before this backstop.) + if m.contains("4.6") || m.contains("4-6") { + if m.contains("fast") { + (4.0, 12.0) + } else { + (2.0, 6.0) + } + } else if m.contains("code") || m.contains("fast") { (0.2, 1.5) } else { (3.0, 15.0) From cdc44a36efa8d2acbb133fea0b73596ecbe5700e Mon Sep 17 00:00:00 2001 From: ItsJazii <144446489+ItsJazii@users.noreply.github.com> Date: Thu, 13 Aug 2026 15:11:49 +0500 Subject: [PATCH 3/3] Scope Cursor branding to the Grok 4.6 entry (Devin review) A generic cursor- prefix strip let every cursor-branded slug reach the whole baked table; cursor-grok-4.6 spellings are now explicit match arms instead, so future Cursor slugs that bill at Cursor rates can never silently price off vendor rate cards. Co-Authored-By: Claude Fable 5 --- src-tauri/src/pricing.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src-tauri/src/pricing.rs b/src-tauri/src/pricing.rs index 570c585b..83b113cd 100644 --- a/src-tauri/src/pricing.rs +++ b/src-tauri/src/pricing.rs @@ -669,11 +669,6 @@ fn builtin_price(canonical: &str) -> Option { .strip_prefix("moonshot/") .or_else(|| canonical.strip_prefix("moonshot-ai/")) .or_else(|| canonical.strip_prefix("xai/")) - // Cursor's CSV brands third-party slugs ("cursor-grok-4.6-xhigh"); - // the supplement's alias rules normally translate these, but a - // launch-day model needs the baked rates before the supplement - // learns the new slug. - .or_else(|| canonical.strip_prefix("cursor-")) .unwrap_or(canonical); match bare { "kimi-k3" | "kimi-k3-code" => Some(Price::flat(3.0, 15.0, 0.3, 3.0)), @@ -689,7 +684,12 @@ fn builtin_price(canonical: &str) -> Option { // plain input. The announced 2x "-fast" variant needs no entry: // the -fast resolution path applies the default 2x multiplier to // this rate card. Public catalogs don't carry 4.6 yet. - "grok-4.6" | "grok-4-6" => Some(Price { + // The cursor- spellings are Cursor's CSV branding for the same + // vendor-billed model ("cursor-grok-4.6-xhigh" on launch day) — + // matched EXPLICITLY rather than via a generic cursor- prefix + // strip, so other cursor-branded slugs (which Cursor may bill at + // its own rates) can never silently price off this baked table. + "grok-4.6" | "grok-4-6" | "cursor-grok-4.6" | "cursor-grok-4-6" => Some(Price { input_200k: Some(4.0), output_200k: Some(12.0), cache_read_200k: Some(1.0),