diff --git a/src-tauri/src/stats.rs b/src-tauri/src/stats.rs index 16dd45e..ff7efdd 100644 --- a/src-tauri/src/stats.rs +++ b/src-tauri/src/stats.rs @@ -86,9 +86,10 @@ impl ContextWarning { /// Get the context window limit (in tokens) for a given model fn get_context_window_limit(model: &str) -> u64 { match model { - // Claude 4.6 family - "claude-opus-4-6" => 200_000, - "claude-sonnet-4-6" => 1_000_000, // 1M token context window + // Claude 4.7 - 1M token context window + "claude-opus-4-7" => 1_000_000, + // Claude 4.6 family - 1M token context window + "claude-opus-4-6" | "claude-sonnet-4-6" => 1_000_000, // Claude 4.5 family - 200K standard context "claude-opus-4-5-20251101" | "claude-sonnet-4-5-20250929" @@ -490,7 +491,7 @@ fn is_consecutive_day(prev_date: &str, current_date: &str) -> bool { } } -// Pricing as of February 2026 +// Pricing as of May 2026 // https://platform.claude.com/docs/en/about-claude/models/overview // Cache pricing: https://platform.claude.com/docs/en/build-with-claude/prompt-caching pub fn calculate_cost( @@ -501,14 +502,17 @@ pub fn calculate_cost( cache_read_tokens: Option, ) -> f64 { let (input_price_per_million, output_price_per_million) = match model { - // Current generation (Claude 4.6) - "claude-opus-4-6" => (5.0, 25.0), + // Current generation (Claude 4.7/4.6/4.5) + "claude-opus-4-7" => (5.0, 25.0), "claude-sonnet-4-6" => (3.0, 15.0), + "claude-haiku-4-5-20251001" => (1.0, 5.0), + + // Previous generation (Claude 4.6) + "claude-opus-4-6" => (5.0, 25.0), // Previous generation (Claude 4.5) "claude-opus-4-5-20251101" => (5.0, 25.0), "claude-sonnet-4-5-20250929" => (3.0, 15.0), - "claude-haiku-4-5-20251001" => (1.0, 5.0), // Previous generation (Claude 4.x) "claude-opus-4-1-20250805" => (15.0, 75.0), @@ -681,6 +685,15 @@ mod tests { assert!((cost - 0.165).abs() < 0.0001); } + #[test] + fn test_cost_calculation_opus_47() { + let cost = calculate_cost(1000, 2000, "claude-opus-4-7", None, None); + // Opus 4.7 pricing: $5/MTok input, $25/MTok output + // 1000 input tokens = $0.005, 2000 output tokens = $0.05 + // Total = $0.055 + assert!((cost - 0.055).abs() < 0.0001); + } + #[test] fn test_cost_calculation_opus_45() { let cost = calculate_cost(1000, 2000, "claude-opus-4-5-20251101", None, None); @@ -1019,6 +1032,16 @@ mod tests { // Context Window Tracking tests // ===================== + #[test] + fn test_context_window_limit_opus_47() { + assert_eq!(get_context_window_limit("claude-opus-4-7"), 1_000_000); + } + + #[test] + fn test_context_window_limit_opus_46() { + assert_eq!(get_context_window_limit("claude-opus-4-6"), 1_000_000); + } + #[test] fn test_context_window_limit_claude_4() { assert_eq!(get_context_window_limit("claude-opus-4-5-20251101"), 200_000); diff --git a/src/lib/components/ConfigSidebar.svelte b/src/lib/components/ConfigSidebar.svelte index 9b2877e..d057762 100644 --- a/src/lib/components/ConfigSidebar.svelte +++ b/src/lib/components/ConfigSidebar.svelte @@ -144,17 +144,20 @@ const availableModels = [ { value: "", label: "Default (from ~/.claude)" }, - // Current generation (Claude 4.6) - { value: "claude-opus-4-6", label: "Claude Opus 4.6 (Most Capable)" }, + // Current generation (Claude 4.7/4.6/4.5) + { value: "claude-opus-4-7", label: "Claude Opus 4.7 (Most Capable)" }, { value: "claude-sonnet-4-6", label: "Claude Sonnet 4.6 (Recommended)" }, + { value: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5 (Fast & Cheap)" }, + // Previous generation (Claude 4.6) + { value: "claude-opus-4-6", label: "Claude Opus 4.6" }, // Previous generation (Claude 4.5) { value: "claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5" }, - { value: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5 (Fast & Cheap)" }, { value: "claude-opus-4-5-20251101", label: "Claude Opus 4.5" }, // Previous generation (Claude 4.x) { value: "claude-opus-4-1-20250805", label: "Claude Opus 4.1" }, - { value: "claude-sonnet-4-20250514", label: "Claude Sonnet 4" }, - { value: "claude-opus-4-20250514", label: "Claude Opus 4" }, + // Deprecated — retire June 15, 2026 + { value: "claude-sonnet-4-20250514", label: "Claude Sonnet 4 (Deprecated)" }, + { value: "claude-opus-4-20250514", label: "Claude Opus 4 (Deprecated)" }, ]; const commonTools = [ diff --git a/src/lib/stores/stats.ts b/src/lib/stores/stats.ts index 46d18cc..0eed746 100644 --- a/src/lib/stores/stats.ts +++ b/src/lib/stores/stats.ts @@ -10,13 +10,15 @@ export type BudgetType = "token" | "cost"; // Model pricing (per million tokens) - keep in sync with stats.rs // Source: https://platform.claude.com/docs/en/about-claude/models/overview export const MODEL_PRICING: Record = { - // Current generation (Claude 4.6) - "claude-opus-4-6": { input: 5.0, output: 25.0 }, + // Current generation (Claude 4.7/4.6/4.5) + "claude-opus-4-7": { input: 5.0, output: 25.0 }, "claude-sonnet-4-6": { input: 3.0, output: 15.0 }, + "claude-haiku-4-5-20251001": { input: 1.0, output: 5.0 }, + // Previous generation (Claude 4.6) + "claude-opus-4-6": { input: 5.0, output: 25.0 }, // Previous generation (Claude 4.5) "claude-opus-4-5-20251101": { input: 5.0, output: 25.0 }, "claude-sonnet-4-5-20250929": { input: 3.0, output: 15.0 }, - "claude-haiku-4-5-20251001": { input: 1.0, output: 5.0 }, // Previous generation (Claude 4.x) "claude-opus-4-1-20250805": { input: 15.0, output: 75.0 }, "claude-opus-4-20250514": { input: 15.0, output: 75.0 },