From 41588bea0100018adf01621e231ef918abddd1ae Mon Sep 17 00:00:00 2001 From: Dasep Moch Luay Date: Wed, 5 Aug 2026 16:31:03 +0700 Subject: [PATCH] feat(providers): add TokenRouter accurate pricing + thinking config Adds exact per-model rates for 110 TokenRouter models (pulled from TokenRouter's own pricing API) plus a dedicated thinkingFormat case (reasoning_effort enum low/medium/high/xhigh/max) and the provider logo. Provider registration itself already landed in a prior commit; this fills in what PR #3043 added on top. --- open-sse/providers/pricing.js | 116 ++++++++++++++++++ open-sse/providers/registry/tokenrouter.js | 12 +- .../translator/concerns/thinkingUnified.js | 9 ++ public/providers/tokenrouter.png | Bin 0 -> 5890 bytes 4 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 public/providers/tokenrouter.png diff --git a/open-sse/providers/pricing.js b/open-sse/providers/pricing.js index 9a0768ef..e9f2b612 100644 --- a/open-sse/providers/pricing.js +++ b/open-sse/providers/pricing.js @@ -141,6 +141,122 @@ export const PROVIDER_PRICING = { gh: { "gpt-5.3-codex": { input: 1.75, output: 14.00, cached: 0.175, reasoning: 14.00, cache_creation: 1.75 }, }, + // TokenRouter — exact rates from https://api.tokenrouter.com/api/pricing ($1/1M tokens). + // Ratio→USD: input = model_ratio×2, output = model_ratio×completion_ratio×2. + // These override the canonical MODEL_PRICING/PATTERN_PRICING, whose rates often + // differ from TokenRouter's reseller pricing. + tokenrouter: { + "MiniMax-M3": { input: 0.3, output: 1.2, cached: 0.06, reasoning: 1.2 }, + "anthropic/claude-fable-5": { input: 10, output: 50, cached: 1.0, cache_creation: 12.5, reasoning: 50 }, + "anthropic/claude-haiku-4.5": { input: 1.0, output: 5.0, cached: 0.1, cache_creation: 1.25, reasoning: 5.0 }, + "anthropic/claude-opus-4.5": { input: 5.0, output: 25.0, cached: 0.5, cache_creation: 6.25, reasoning: 25.0 }, + "anthropic/claude-opus-4.6": { input: 5.0, output: 25.0, cached: 0.5, cache_creation: 6.25, reasoning: 25.0 }, + "anthropic/claude-opus-4.7": { input: 5.0, output: 25.0, cached: 0.5, cache_creation: 6.25, reasoning: 25.0 }, + "anthropic/claude-opus-4.7-fast": { input: 30, output: 150, cached: 3.0, reasoning: 150 }, + "anthropic/claude-opus-4.8": { input: 5.0, output: 25.0, cached: 0.5, cache_creation: 6.25, reasoning: 25.0 }, + "anthropic/claude-opus-4.8-fast": { input: 10, output: 50, cached: 1.0, cache_creation: 12.5, reasoning: 50 }, + "anthropic/claude-opus-5": { input: 5.0, output: 25.0, cached: 0.5, cache_creation: 6.25, reasoning: 25.0 }, + "anthropic/claude-opus-5-fast": { input: 10, output: 50, cached: 1.0, cache_creation: 12.5, reasoning: 50 }, + "anthropic/claude-sonnet-4": { input: 3.0, output: 15.0, cached: 0.3, cache_creation: 3.75, reasoning: 15.0 }, + "anthropic/claude-sonnet-4.5": { input: 3.0, output: 15.0, cached: 0.3, cache_creation: 3.75, reasoning: 15.0 }, + "anthropic/claude-sonnet-4.6": { input: 3.0, output: 15.0, cached: 0.3, cache_creation: 3.75, reasoning: 15.0 }, + "anthropic/claude-sonnet-5": { input: 2, output: 10, cached: 0.2, reasoning: 10 }, + "claude-opus-4-8-m-aws": { input: 5.0, output: 25.0, cached: 0.5, cache_creation: 6.25, reasoning: 25.0 }, + "deepseek/deepseek-v3.2": { input: 0.26, output: 0.38, cached: 0.13, reasoning: 0.38 }, + "deepseek/deepseek-v4-flash": { input: 0.14, output: 0.28, cached: 0.0028, reasoning: 0.28 }, + "deepseek/deepseek-v4-flash-0731": { input: 0.14, output: 0.28, cached: 0.0028, reasoning: 0.28 }, + "deepseek/deepseek-v4-pro": { input: 0.435, output: 0.87, cached: 0.003625, reasoning: 0.87 }, + "ex/gpt-5.4": { input: 2.5, output: 15.0, cached: 0.25, reasoning: 15.0 }, + "google/gemini-2.5-flash-image": { input: 0.3, output: 2.5, reasoning: 2.5 }, + "google/gemini-3-flash-preview": { input: 0.5, output: 3.0, cached: 0.05, cache_creation: 0.08333, reasoning: 3.0 }, + "google/gemini-3-pro-image-preview": { input: 2, output: 12, reasoning: 12 }, + "google/gemini-3.1-flash-image-preview": { input: 0.5, output: 3.0, reasoning: 3.0 }, + "google/gemini-3.1-flash-lite-image": { input: 0.25, output: 1.5, reasoning: 1.5 }, + "google/gemini-3.1-pro-preview": { input: 2, output: 12, cached: 0.2, cache_creation: 0.375, reasoning: 12 }, + "google/gemini-3.5-flash": { input: 1.5, output: 9.0, cached: 0.15, cache_creation: 0.08333, reasoning: 9.0 }, + "google/gemini-3.5-flash-lite": { input: 0.3, output: 2.5, cached: 0.03, cache_creation: 0.08333, reasoning: 2.5 }, + "google/gemini-3.6-flash": { input: 1.5, output: 7.5, cached: 0.15, cache_creation: 0.08333, reasoning: 7.5 }, + "google/gemini-embedding-2": { input: 1.0, output: 6.0, cached: 0.1, reasoning: 6.0 }, + "google/gemma-4-26b-a4b-it": { input: 0.06, output: 0.33, reasoning: 0.33 }, + "kling-3.0-turbo": { input: 2.1, output: 2.1, reasoning: 2.1 }, + "microsoft/mai-image-2.5": { input: 5.0, output: 47.0, reasoning: 47.0 }, + "minimax/minimax-m2-her": { input: 0.3, output: 1.2, cached: 0.03, reasoning: 1.2 }, + "minimax/minimax-m2.1": { input: 0.3, output: 1.2, cached: 0.03, reasoning: 1.2 }, + "minimax/minimax-m2.1-highspeed": { input: 0.6, output: 2.4, cached: 0.06, reasoning: 2.4 }, + "minimax/minimax-m2.5": { input: 0.3, output: 1.2, cached: 0.03, reasoning: 1.2 }, + "minimax/minimax-m2.7": { input: 0.3, output: 1.2, cached: 0.06, reasoning: 1.2 }, + "minimax/minimax-m2.7-highspeed": { input: 0.6, output: 2.4, cached: 0.06, reasoning: 2.4 }, + "miromind/mirothinker-1-7-deepresearch": { input: 4, output: 25.0, reasoning: 25.0 }, + "miromind/mirothinker-1-7-deepresearch-mini": { input: 1.25, output: 10.0, reasoning: 10.0 }, + "mistralai/devstral-2512": { input: 0.4, output: 2.0, cached: 0.04, reasoning: 2.0 }, + "mistralai/mistral-medium-3-5": { input: 1.5, output: 7.5, reasoning: 7.5 }, + "mistralai/mistral-small-2603": { input: 0.15, output: 0.6, cached: 0.015, reasoning: 0.6 }, + "mistralai/voxtral-small-24b-2507": { input: 0.1, output: 0.3, cached: 0.01, reasoning: 0.3 }, + "moonshotai/kimi-k2.5": { input: 0.6, output: 3.0, cached: 0.1, reasoning: 3.0 }, + "moonshotai/kimi-k2.6": { input: 0.95, output: 4.0, cached: 0.16, reasoning: 4.0 }, + "moonshotai/kimi-k2.7-code": { input: 0.9286, output: 3.8571, cached: 0.1857, reasoning: 3.8571 }, + "moonshotai/kimi-k3": { input: 3.0, output: 15.0, cached: 0.3, reasoning: 15.0 }, + "nvidia/nemotron-3-super-120b-a12b": { input: 0.3, output: 0.9, cached: 0.1, reasoning: 0.9 }, + "openai/gpt-4o-mini": { input: 0.15, output: 0.6, cached: 0.075, reasoning: 0.6 }, + "openai/gpt-5": { input: 1.25, output: 10.0, cached: 0.125, reasoning: 10.0 }, + "openai/gpt-5-image": { input: 10, output: 40, cached: 2.5, reasoning: 40 }, + "openai/gpt-5-image-mini": { input: 2.5, output: 8.0, cached: 0.25, reasoning: 8.0 }, + "openai/gpt-5-mini": { input: 0.25, output: 2.0, cached: 0.025, reasoning: 2.0 }, + "openai/gpt-5.2": { input: 1.75, output: 14.0, cached: 0.175, reasoning: 14.0 }, + "openai/gpt-5.3-codex": { input: 1.75, output: 14.0, cached: 0.175, reasoning: 14.0 }, + "openai/gpt-5.4": { input: 2.5, output: 15.0, cached: 0.25, reasoning: 15.0 }, + "openai/gpt-5.4-image-2": { input: 8, output: 30.0, cached: 2.0, reasoning: 30.0 }, + "openai/gpt-5.4-mini": { input: 0.75, output: 4.5, cached: 0.075, reasoning: 4.5 }, + "openai/gpt-5.4-nano": { input: 0.2, output: 1.25, cached: 0.02, reasoning: 1.25 }, + "openai/gpt-5.4-pro": { input: 30, output: 180, reasoning: 180 }, + "openai/gpt-5.5": { input: 5.0, output: 30.0, cached: 0.5, reasoning: 30.0 }, + "openai/gpt-5.5-pro": { input: 30, output: 180, reasoning: 180 }, + "openai/gpt-5.6-luna": { input: 0.2, output: 1.2, cached: 0.02, cache_creation: 0.25, reasoning: 1.2 }, + "openai/gpt-5.6-sol": { input: 5.0, output: 30.0, cached: 0.5, cache_creation: 6.25, reasoning: 30.0 }, + "openai/gpt-5.6-terra": { input: 2, output: 12, cached: 0.2, cache_creation: 2.5, reasoning: 12 }, + "openai/gpt-audio": { input: 2.5, output: 10.0, reasoning: 10.0 }, + "openai/gpt-audio-mini": { input: 0.6, output: 2.4, reasoning: 2.4 }, + "openai/gpt-oss-120b": { input: 0.039, output: 0.18, reasoning: 0.18 }, + "qwen/qwen3-coder-next": { input: 0.12, output: 0.75, cached: 0.06, reasoning: 0.75 }, + "qwen/qwen3.5-122b-a10b": { input: 0.26, output: 2.08, reasoning: 2.08 }, + "qwen/qwen3.5-35b-a3b": { input: 0.1625, output: 1.3, reasoning: 1.3 }, + "qwen/qwen3.5-397b-a17b": { input: 0.39, output: 2.34, reasoning: 2.34 }, + "qwen/qwen3.5-9b": { input: 0.1, output: 0.15, reasoning: 0.15 }, + "qwen/qwen3.5-flash": { input: 0.1048, output: 0.4194, reasoning: 0.4194 }, + "qwen/qwen3.5-plus-02-15": { input: 0.26, output: 1.56, reasoning: 1.56 }, + "qwen/qwen3.6-plus": { input: 0.54, output: 3.21, reasoning: 3.21 }, + "qwen/qwen3.7-max": { input: 1.25, output: 3.75, cached: 0.25, reasoning: 3.75 }, + "qwen/qwen3.7-plus": { input: 0.4, output: 1.6, cached: 0.08, reasoning: 1.6 }, + "qwen/qwen3.8-max": { input: 2, output: 6, cached: 0.25, cache_creation: 2.5, reasoning: 6 }, + "qwen3.5-omni-plus": { input: 1.0, output: 5.7143, reasoning: 5.7143 }, + "qwen3.6-flash": { input: 0.171, output: 1.029, cached: 0.017, cache_creation: 0.214, reasoning: 1.029 }, + "sakana/fugu-ultra": { input: 5.0, output: 30.0, cached: 0.5, reasoning: 30.0 }, + "seed-2-0-code-preview-260328": { input: 1.0, output: 6.0, cached: 0.2, cache_creation: 0.008333, reasoning: 6.0 }, + "seed-2-0-lite-260428": { input: 0.5, output: 4.0, cached: 0.1, cache_creation: 0.008333, reasoning: 4.0 }, + "seed-2-0-mini-260428": { input: 0.2, output: 0.8, cached: 0.04, cache_creation: 0.00833, reasoning: 0.8 }, + "seed-2-0-pro-260328": { input: 1.0, output: 6.0, cached: 0.2, cache_creation: 0.008333, reasoning: 6.0 }, + "stepfun/step-3.5-flash": { input: 0.1, output: 0.3, cached: 0.02, reasoning: 0.3 }, + "stepfun/step-3.7-flash": { input: 0.2, output: 1.15, cached: 0.04, reasoning: 1.15 }, + "tencent/hy3-preview": { input: 0.066, output: 0.26, cached: 0.029, reasoning: 0.26 }, + "x-ai/grok-4.1-fast": { input: 0.2, output: 0.5, cached: 0.05, reasoning: 0.5 }, + "x-ai/grok-4.20-beta": { input: 2, output: 6, cached: 0.2, reasoning: 6 }, + "x-ai/grok-4.3": { input: 1.25, output: 2.5, cached: 0.2, reasoning: 2.5 }, + "x-ai/grok-4.5": { input: 2, output: 6, cached: 0.5, reasoning: 6 }, + "x-ai/grok-build-0.1": { input: 1.0, output: 2.0, cached: 0.2, reasoning: 2.0 }, + "xiaomi/mimo-v2-flash": { input: 0.1, output: 0.3, cached: 0.01, reasoning: 0.3 }, + "xiaomi/mimo-v2-omni": { input: 0.4, output: 2.0, cached: 0.08, reasoning: 2.0 }, + "xiaomi/mimo-v2-pro": { input: 1.0, output: 3.0, cached: 0.2, reasoning: 3.0 }, + "xiaomi/mimo-v2.5": { input: 0.4, output: 2.0, cached: 0.08, reasoning: 2.0 }, + "xiaomi/mimo-v2.5-pro": { input: 1.0, output: 3.0, cached: 0.2, reasoning: 3.0 }, + "z-ai/glm-4.5-air": { input: 0.13, output: 0.85, cached: 0.025, reasoning: 0.85 }, + "z-ai/glm-4.6": { input: 0.6, output: 2.2, cached: 0.11, reasoning: 2.2 }, + "z-ai/glm-4.6v": { input: 0.3, output: 0.9, reasoning: 0.9 }, + "z-ai/glm-4.7": { input: 0.6, output: 2.2, cached: 0.11, reasoning: 2.2 }, + "z-ai/glm-5": { input: 1.0, output: 3.2, cached: 0.2, reasoning: 3.2 }, + "z-ai/glm-5-turbo": { input: 1.2, output: 4.0, cached: 0.24, reasoning: 4.0 }, + "z-ai/glm-5.1": { input: 1.05, output: 3.5, cached: 0.525, reasoning: 3.5 }, + "z-ai/glm-5.2": { input: 1.4, output: 4.4, cached: 0.26, reasoning: 4.4 }, + }, }; /** diff --git a/open-sse/providers/registry/tokenrouter.js b/open-sse/providers/registry/tokenrouter.js index 8c5bf49f..2e3cd248 100644 --- a/open-sse/providers/registry/tokenrouter.js +++ b/open-sse/providers/registry/tokenrouter.js @@ -15,13 +15,17 @@ export default { }, }, category: "apikey", + thinkingConfig: { + options: ["low", "medium", "high", "xhigh", "max"], + defaultMode: "high", + }, transport: { baseUrl: "https://api.tokenrouter.com/v1/chat/completions", validateUrl: "https://api.tokenrouter.com/v1/models", - thinkingFormat: "openai", + thinkingFormat: "tokenrouter", }, - // Seed snapshot dari live /v1/models (118 entri, 2026-07-31). Catalogue terbaru - // di-fetch via modelsFetcher; id lain tetap diterima via passthroughModels. + // Seed snapshot from live /v1/models (120 entries). Latest catalogue is + // fetched via modelsFetcher; other ids still accepted via passthroughModels. models: [ { id: "MiniMax-Hailuo-2.3", name: "Minimax Hailuo 2.3", kind: "video" }, { id: "MiniMax-M3", name: "Minimax M3" }, @@ -46,6 +50,7 @@ export default { { id: "claude-opus-4-8-m-aws", name: "Claude Opus 4 8 M Aws" }, { id: "deepseek/deepseek-v3.2", name: "Deepseek V3.2" }, { id: "deepseek/deepseek-v4-flash", name: "Deepseek V4 Flash" }, + { id: "deepseek/deepseek-v4-flash-0731", name: "Deepseek V4 Flash 0731" }, { id: "deepseek/deepseek-v4-pro", name: "Deepseek V4 Pro" }, { id: "ex/gpt-5.4", name: "Gpt 5.4" }, { id: "google/gemini-2.5-flash-image", name: "Gemini 2.5 Flash Image" }, @@ -113,6 +118,7 @@ export default { { id: "qwen/qwen3.6-plus", name: "Qwen3.6 Plus" }, { id: "qwen/qwen3.7-max", name: "Qwen3.7 Max" }, { id: "qwen/qwen3.7-plus", name: "Qwen3.7 Plus" }, + { id: "qwen/qwen3.8-max", name: "Qwen3.8 Max" }, { id: "qwen3.5-omni-plus", name: "Qwen3.5 Omni Plus" }, { id: "qwen3.6-flash", name: "Qwen3.6 Flash" }, { id: "sakana/fugu-ultra", name: "Fugu Ultra" }, diff --git a/open-sse/translator/concerns/thinkingUnified.js b/open-sse/translator/concerns/thinkingUnified.js index 5dbf756b..d18f47b6 100644 --- a/open-sse/translator/concerns/thinkingUnified.js +++ b/open-sse/translator/concerns/thinkingUnified.js @@ -310,6 +310,15 @@ function applyFormat(fmt, body, cfg, caps, supportedLevels) { if (level) body.reasoning_effort = level === "xhigh" || level === "max" ? "high" : level; break; } + case "tokenrouter": { + // TokenRouter's reasoning_effort enum is low/medium/high/xhigh/max — it rejects + // "none"/"auto" with a 400 and supports "max" natively (no clamp like openai). + // "none" → omit the field so the upstream default applies; pass levels through. + if (none || eff.mode === "auto") break; + const level = toLevel(eff); + if (level) body.reasoning_effort = level; + break; + } case "kiro": // Kiro thinking handled via system-tag injection in openai-to-kiro.js; no body field here. break; diff --git a/public/providers/tokenrouter.png b/public/providers/tokenrouter.png new file mode 100644 index 0000000000000000000000000000000000000000..58f7eac234aefcb4651ad33625fd3254ee2f587b GIT binary patch literal 5890 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