-
Notifications
You must be signed in to change notification settings - Fork 8
Grok 4.6 launch pricing, Cursor slug handling, DeepSeek v4 builtins #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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: deepseek-v4 pro/flash builtin prices | ||
|
|
||
| /// Stable fingerprint of the effective pricing inputs: the on-disk catalog | ||
| /// files plus this binary's corrections revision. The persistent spend | ||
|
|
@@ -668,13 +668,49 @@ fn builtin_price(canonical: &str) -> Option<Price> { | |
| let bare = canonical | ||
| .strip_prefix("moonshot/") | ||
| .or_else(|| canonical.strip_prefix("moonshot-ai/")) | ||
| .or_else(|| canonical.strip_prefix("xai/")) | ||
| .or_else(|| canonical.strip_prefix("deepseek/")) | ||
| // 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); | ||
| // DeepSeek ships dated snapshots ("deepseek-v4-pro-0813"); price them as | ||
| // the base model so a new date doesn't silently go unpriced. | ||
| let bare = match bare.strip_suffix(|c: char| c.is_ascii_digit()) { | ||
| Some(_) if bare.starts_with("deepseek-") => bare.rsplit_once('-').map_or(bare, |(h, t)| { | ||
| if t.chars().all(|c| c.is_ascii_digit()) && t.len() >= 4 { h } else { bare } | ||
| }), | ||
| _ => bare, | ||
| }; | ||
|
Comment on lines
+679
to
+686
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔍 Dated-snapshot stripping is scoped tightly, but only to The snapshot trimmer at Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| match bare { | ||
| // AihubMix DeepSeek V4 family (USD/MTok, aihubmix.com/model/…): no | ||
| // cache-write rate published, so writes bill at the input rate. | ||
| // Used through Hermes/AihubMix; public catalogs don't carry these | ||
| // slugs yet. pro: /deepseek-v4-pro-0813 · flash: /deepseek-v4-flash. | ||
| "deepseek-v4-pro" => Some(Price::flat(0.464, 0.928, 0.004, 0.464)), | ||
| "deepseek-v4-flash" => Some(Price::flat(0.142, 0.284, 0.0284, 0.142)), | ||
|
Comment on lines
+692
to
+693
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Cached input on one DeepSeek model is billed at roughly a tenth of the plausible rate The cached-input rate for DeepSeek's pro model is set to $0.004 per million ( Rate-card ratio inconsistency inside the same baked-in familyBoth new entries mirror each other everywhere else (output = 2× input, cache write = input). The flash entry's cache read Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| "kimi-k3" | "kimi-k3-code" => Some(Price::flat(3.0, 15.0, 0.3, 3.0)), | ||
| // Alibaba Model Studio, GA'd 2026-08-03 (USD/MTok): input $2, | ||
| // 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, | ||
| } | ||
| } | ||
|
|
@@ -725,6 +761,25 @@ mod tests { | |
| assert!((baked.input - 2.0).abs() < 1e-9); | ||
| } | ||
|
|
||
| #[test] | ||
| fn deepseek_v4_pro_is_priced_including_dated_snapshots() { | ||
| let store = super::Store::default(); | ||
| // Bare slug and the AihubMix dated snapshot both price identically. | ||
| for slug in ["deepseek-v4-pro", "deepseek-v4-pro-0813", "deepseek/deepseek-v4-pro-0813"] { | ||
| let p = super::resolve(&store, slug, 0).unwrap_or_else(|| panic!("{slug} unpriced")); | ||
| assert!((p.input - 0.464).abs() < 1e-9, "{slug}"); | ||
| assert!((p.output - 0.928).abs() < 1e-9, "{slug}"); | ||
| assert!((p.cache_read - 0.004).abs() < 1e-9, "{slug}"); | ||
| } | ||
| // The flash sibling is priced too (both are Hermes-logged slugs), | ||
| // including its dated snapshot. | ||
| let flash = super::resolve(&store, "deepseek-v4-flash-0731", 0).unwrap(); | ||
| assert!((flash.input - 0.142).abs() < 1e-9); | ||
| assert!((flash.output - 0.284).abs() < 1e-9); | ||
| // A slug outside the family stays unpriced (no over-broad match). | ||
| assert!(super::resolve(&store, "deepseek-v9-imaginary", 0).is_none()); | ||
| } | ||
|
|
||
| #[test] | ||
| fn priority_slugs_price_at_base_times_priority_multiplier() { | ||
| let mut store = super::Store::default(); | ||
|
|
@@ -768,6 +823,33 @@ 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(); | ||
| // 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}"); | ||
| 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 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Pull request bundles three unrelated changes despite the one-change rule
This change ships launch pricing for one vendor's new model, a separate vendor-prefix stripping rule, and a third vendor's model family in a single pull request (see the changelog entries added at
CHANGELOG.md:5-16), which the project's contribution rules forbid.Impact: Reviewers cannot accept or revert one part without the others.
CONTRIBUTING.md rule
CONTRIBUTING.mdstates under Pull requests: "Keep PRs focused: one change per PR." The PR title itself names three separate items (Grok 4.6 launch pricing, Cursor slug handling, DeepSeek v4 builtins), and the code changes touch independent builtin entries insrc-tauri/src/pricing.rs:667-716plus a backstop table insrc-tauri/src/spend.rs:414-432.Was this helpful? React with 👍 or 👎 to provide feedback.