mirror of
https://github.com/instructkr/claw-code.git
synced 2026-10-27 00:00:00 +08:00
feat(runtime): add OpenAI, xAI, and DashScope pricing (#3358)
Models from the OpenAI-compatible providers fell back to default_sonnet_tier ($3/$15 per MTok), so e.g. gpt-5.4-nano was estimated at 15x its input price and qwen-plus at about 26x. Add a table of published rates keyed by model id, matching dated snapshots and -latest aliases: - OpenAI standard tier for current gpt-6 / gpt-5.x / gpt-4.1 / gpt-4o and o-series models (Responses-only pro models are omitted). - xAI grok-4.x and grok-build. Slugs retired on 2026-05-15 (grok-3, grok-4-0709, grok-4-fast-*, grok-4-1-fast-*) are billed at grok-4.3 rates, and grok-code-fast-* is served as grok-build. - DashScope qwen-max, qwen-plus, qwen-flash and kimi-k2.5 at China (Beijing) rates, which is claw's default DashScope endpoint, with non-thinking output and the 20% implicit-cache hit rate. Long-context and higher input tiers use the base rate because usage is aggregated across requests.
This commit is contained in:
1 parent
b8f93afbb3
commit
3cc90cfc7a
1 file changed
+122
-1
@@ -122,7 +122,88 @@ pub fn pricing_for_model(model: &str) -> Option<ModelPricing> {
|
||||
{
|
||||
return Some(ModelPricing::per_million(0.3, 1.2, 0.3, 0.006));
|
||||
}
|
||||
None
|
||||
openai_compatible_pricing(&normalized)
|
||||
}
|
||||
|
||||
/// xAI bills slugs retired on 2026-05-15 at grok-4.3 rates
|
||||
/// (<https://docs.x.ai/developers/migration/may-15-retirement>).
|
||||
const GROK_4_3: [f64; 4] = [1.25, 2.5, 1.25, 0.2];
|
||||
const GROK_BUILD: [f64; 4] = [1.0, 2.0, 1.0, 0.2];
|
||||
|
||||
/// Input, output, cache-write and cache-read rates per MTok for models served through
|
||||
/// OpenAI-compatible providers, keyed by model id.
|
||||
///
|
||||
/// An id also matches its dated snapshots and `-latest` alias (e.g. `gpt-4.1-2025-04-14`),
|
||||
/// so a specific snapshot must precede its base id. Long-context and higher input tiers
|
||||
/// are not modeled because usage is aggregated across requests. Cache writes without a
|
||||
/// separate charge, and models without a cached-input discount, use the input rate.
|
||||
const OPENAI_COMPATIBLE_PRICING: &[(&str, [f64; 4])] = &[
|
||||
// OpenAI standard tier (<https://developers.openai.com/api/docs/pricing>).
|
||||
("gpt-6-astra", [10.0, 50.0, 12.5, 1.0]),
|
||||
("gpt-6.1-sol", [2.0, 10.0, 2.5, 0.1]),
|
||||
("gpt-6-sol", [2.0, 10.0, 2.5, 0.2]),
|
||||
("gpt-6-luna", [0.1, 0.5, 0.125, 0.01]),
|
||||
("gpt-5.6-sol", [4.0, 20.0, 5.0, 0.4]),
|
||||
("gpt-5.6-terra", [2.0, 12.0, 2.5, 0.2]),
|
||||
("gpt-5.6-luna", [0.2, 1.2, 0.25, 0.02]),
|
||||
("gpt-5.5", [5.0, 30.0, 5.0, 0.5]),
|
||||
("gpt-5.4", [2.5, 15.0, 2.5, 0.25]),
|
||||
("gpt-5.4-mini", [0.75, 4.5, 0.75, 0.075]),
|
||||
("gpt-5.4-nano", [0.2, 1.25, 0.2, 0.02]),
|
||||
("gpt-5.2", [1.75, 14.0, 1.75, 0.175]),
|
||||
("gpt-5.1", [1.25, 10.0, 1.25, 0.125]),
|
||||
("gpt-5", [1.25, 10.0, 1.25, 0.125]),
|
||||
("gpt-5-mini", [0.25, 2.0, 0.25, 0.025]),
|
||||
("gpt-5-nano", [0.05, 0.4, 0.05, 0.005]),
|
||||
("gpt-4.1", [2.0, 8.0, 2.0, 0.5]),
|
||||
("gpt-4.1-mini", [0.4, 1.6, 0.4, 0.1]),
|
||||
("gpt-4.1-nano", [0.1, 0.4, 0.1, 0.025]),
|
||||
("gpt-4o-2024-05-13", [5.0, 15.0, 5.0, 5.0]),
|
||||
("gpt-4o", [2.5, 10.0, 2.5, 1.25]),
|
||||
("gpt-4o-mini", [0.15, 0.6, 0.15, 0.075]),
|
||||
("o1", [15.0, 60.0, 15.0, 7.5]),
|
||||
("o3", [2.0, 8.0, 2.0, 0.5]),
|
||||
("o3-mini", [1.1, 4.4, 1.1, 0.55]),
|
||||
("o4-mini", [1.1, 4.4, 1.1, 0.275]),
|
||||
// xAI (<https://docs.x.ai/docs/models>).
|
||||
("grok-4.7", [2.0, 6.0, 2.0, 0.5]),
|
||||
("grok-4.6", [2.0, 6.0, 2.0, 0.5]),
|
||||
("grok-4.5", [2.0, 6.0, 2.0, 0.3]),
|
||||
("grok-4.3", GROK_4_3),
|
||||
("grok-4.20", GROK_4_3),
|
||||
("grok-4.20-reasoning", GROK_4_3),
|
||||
("grok-4.20-non-reasoning", GROK_4_3),
|
||||
("grok-4.20-multi-agent", GROK_4_3),
|
||||
("grok-build", GROK_BUILD),
|
||||
("grok-code-fast", GROK_BUILD),
|
||||
("grok-4", GROK_4_3),
|
||||
("grok-4-fast-reasoning", GROK_4_3),
|
||||
("grok-4-fast-non-reasoning", GROK_4_3),
|
||||
("grok-3", GROK_4_3),
|
||||
// Alibaba Model Studio, China (Beijing) region, which is claw's default DashScope
|
||||
// endpoint (<https://www.alibabacloud.com/help/en/model-studio/model-pricing>).
|
||||
// Non-thinking output; implicit cache hits bill at 20% of input.
|
||||
("qwen-max", [0.345, 1.377, 0.345, 0.069]),
|
||||
("qwen-plus", [0.115, 0.287, 0.115, 0.023]),
|
||||
("qwen-flash", [0.022, 0.216, 0.022, 0.0044]),
|
||||
("kimi-k2.5", [0.574, 3.011, 0.574, 0.1148]),
|
||||
];
|
||||
|
||||
fn openai_compatible_pricing(normalized: &str) -> Option<ModelPricing> {
|
||||
let id = normalized.rsplit_once('/').map_or(normalized, |(_, id)| id);
|
||||
OPENAI_COMPATIBLE_PRICING
|
||||
.iter()
|
||||
.find(|(model, _)| {
|
||||
id.strip_prefix(model).is_some_and(|rest| {
|
||||
rest.is_empty()
|
||||
|| rest.strip_prefix('-').is_some_and(|suffix| {
|
||||
suffix == "latest" || suffix.starts_with(|c: char| c.is_ascii_digit())
|
||||
})
|
||||
})
|
||||
})
|
||||
.map(|&(_, [input, output, cache_write, cache_read])| {
|
||||
ModelPricing::per_million(input, output, cache_write, cache_read)
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses the `(major, minor)` version after `family` in ids such as
|
||||
@@ -396,6 +477,46 @@ mod tests {
|
||||
assert_eq!(pricing_for_model("deepseek-r1"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prices_openai_compatible_provider_models() {
|
||||
let usage = TokenUsage {
|
||||
input_tokens: 1_000_000,
|
||||
output_tokens: 500_000,
|
||||
cache_creation_input_tokens: 0,
|
||||
cache_read_input_tokens: 1_000_000,
|
||||
};
|
||||
let total_for = |model: &str| {
|
||||
let pricing = pricing_for_model(model).expect("known model pricing");
|
||||
format_usd(
|
||||
usage
|
||||
.estimate_cost_usd_with_pricing(pricing)
|
||||
.total_cost_usd(),
|
||||
)
|
||||
};
|
||||
|
||||
assert_eq!(total_for("gpt-5.4-mini"), "$3.0750");
|
||||
assert_eq!(total_for("openai/gpt-4.1-2025-04-14"), "$6.5000");
|
||||
assert_eq!(total_for("gpt-4o-2024-08-06"), "$8.7500");
|
||||
assert_eq!(total_for("gpt-4o-2024-05-13"), "$17.5000");
|
||||
assert_eq!(total_for("o3-mini"), "$3.8500");
|
||||
assert_eq!(total_for("grok-4.3"), "$2.7000");
|
||||
// Retired xAI slugs are billed as grok-4.3.
|
||||
assert_eq!(total_for("grok-3"), "$2.7000");
|
||||
assert_eq!(total_for("grok-4-1-fast-reasoning"), "$2.7000");
|
||||
assert_eq!(total_for("grok-code-fast-1"), "$2.2000");
|
||||
assert_eq!(total_for("qwen/qwen-max"), "$1.1025");
|
||||
assert_eq!(total_for("qwen-plus-latest"), "$0.2815");
|
||||
assert_eq!(total_for("kimi-k2.5"), "$2.1943");
|
||||
for unpriced in [
|
||||
"o1-mini",
|
||||
"grok-3-mini",
|
||||
"qwen-turbo",
|
||||
"qwen-plus-character",
|
||||
] {
|
||||
assert_eq!(pricing_for_model(unpriced), None, "{unpriced}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn marks_unknown_model_pricing_as_fallback() {
|
||||
let usage = TokenUsage {
|
||||
|
||||
Reference in new issue
Block a user