@blockrun/clawrouter 0.12.248 → 0.12.250

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,10 +46,10 @@ Every other LLM router was built for **human developers** — create an account,
46
46
 
47
47
  ClawRouter is built for the agent-first world:
48
48
 
49
- - **Starts at $0** — <!-- br:models.free -->5<!-- /br:models.free --> NVIDIA models are free forever (incl. 1M-context DeepSeek V4 Flash + a vision-capable Nemotron Omni)
49
+ - **Starts at $0** — <!-- br:models.free -->5<!-- /br:models.free --> NVIDIA models are free forever (incl. reasoning-grade Step 3.7 Flash + a vision-capable Nemotron Omni)
50
50
  - **No accounts** — a wallet is generated locally, no signup
51
51
  - **No API keys** — your wallet signature IS authentication
52
- - **No model selection** — <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions -->-dimension scoring picks the right model automatically
52
+ - **No model selection** — <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions -->-dimension scoring + constraint-first ranking ([router-core](https://github.com/BlockRunAI/router-core)) picks the right model automatically
53
53
  - **No credit cards** — agents pay per-request with USDC via [x402](https://x402.org)
54
54
  - **No trust required** — runs locally, <1ms routing, zero external dependencies
55
55
 
@@ -188,14 +188,12 @@ response = client.chat.completions.create(model="blockrun/auto", messages=[...])
188
188
 
189
189
  Choose your routing strategy with `/model <profile>`:
190
190
 
191
- | Profile | Strategy | Savings | Best For |
192
- | ------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
193
- | `/model free` | Free NVIDIA models | **100%** | $0 balance, learning |
194
- | `/model auto` | Balanced (default) | † Withheld from `/v1/models` — the router still calls it by direct ID, but you will not find it on the public pricing page. See [savings-mix.json](https://github.com/BlockRunAI/blockrun/blob/main/src/brand/savings-mix.json), which prices the published savings claim on visible models only. |
195
-
196
- **<!-- br:savings.autoVsBaselinePct -->88<!-- /br:savings.autoVsBaselinePct -->%** | General use |
197
- | `/model eco` | Cheapest possible | **<!-- br:savings.ecoVsBaselinePct -->98<!-- /br:savings.ecoVsBaselinePct -->%** | Maximum savings |
198
- | `/model premium` | Best quality | 0% | Mission-critical |
191
+ | Profile | Strategy | Savings | Best For |
192
+ | ---------------- | ------------------ | ---------------------------------------------------------------------------------- | -------------------- |
193
+ | `/model free` | Free NVIDIA models | **100%** | $0 balance, learning |
194
+ | `/model auto` | Balanced (default) | **<!-- br:savings.autoVsBaselinePct -->88<!-- /br:savings.autoVsBaselinePct -->%** | General use |
195
+ | `/model eco` | Cheapest possible | **<!-- br:savings.ecoVsBaselinePct -->98<!-- /br:savings.ecoVsBaselinePct -->%** | Maximum savings |
196
+ | `/model premium` | Best quality | 0% | Mission-critical |
199
197
 
200
198
  **Shortcuts:** `/model grok`, `/model br-sonnet`, `/model gpt5`, `/model o3`
201
199
 
@@ -205,18 +203,31 @@ Choose your routing strategy with `/model <profile>`:
205
203
 
206
204
  **100% local routing. <1ms latency. Zero external API calls.**
207
205
 
208
- The scorer weighs <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions of the request:
206
+ Routing decisions come from [`@blockrun/router-core`](https://github.com/BlockRunAI/router-core) — Router Core **V3.4**, the constraint-first portfolio router shared by every BlockRun product (ClawRouter, Franklin, the `@blockrun/llm` SDKs, ClawRouter-Hermes). ClawRouter inlines it at build time, pinned to an exact commit, and injects its live model catalog at startup.
209
207
 
210
208
  ```
211
- Request → Weighted Scorer → Tier → Best Model → Response
209
+ Request → 15-dimension scorer → tier + task shape
210
+ → hard filters (tools · vision · context · max-output · structured output)
211
+ → rank survivors (quality · capability · cost · speed · reliability)
212
+ → winner + ordered fallback chain → Response
212
213
  ```
213
214
 
214
- | Tier | ECO Model | AUTO Model | PREMIUM Model |
215
- | --------- | --------------------------------------- | --------------------------------------- | ---------------------------- |
216
- | SIMPLE | step-3.7-flash (**FREE**) | gemini-2.5-flash ($0.30/$2.50) | kimi-k2.7 † ($0.95/$4.00) |
217
- | MEDIUM | gemini-3.1-flash-lite ($0.25/$1.50) | kimi-k2.7 ($0.95/$4.00) | gpt-5.3-codex ($1.75/$14.00) |
218
- | COMPLEX | gemini-3.1-flash-lite ($0.25/$1.50) | gemini-3.1-pro ($2/$12) | claude-fable-5 ($10/$50) |
219
- | REASONING | grok-4-1-fast-reasoning † ($0.20/$0.50) | grok-4-1-fast-reasoning † ($0.20/$0.50) | claude-sonnet-4.6 ($3/$15) |
215
+ 1. **Classify** — a <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions -->-dimension weighted scorer picks a tier (`SIMPLE` / `MEDIUM` / `COMPLEX` / `REASONING`); a task classifier labels the shape of the work (`code_agent`, `tool_agent`, `reasoning_math`, `long_context`, `vision`, …). Turns that actually need their tools switch to agent-tuned tiers automatically.
216
+ 2. **Filter** — every model that cannot satisfy the request is dropped _before_ anything is scored. A model that can't call tools, can't read the image, or can't hold the conversation never gets to win on price.
217
+ 3. **Rank** — survivors are scored on task quality, capability, estimated cost, speed and reliability, with per-profile weights (`eco` leans on cost, `premium` on quality and reliability).
218
+ 4. **Recover** — the whole ranked list rides along as the fallback chain, so a provider timeout or 5xx costs a retry, not the task.
219
+
220
+ | Tier | ECO Model | AUTO Model | PREMIUM Model | AGENTIC Model ‡ |
221
+ | --------- | --------------------------------------- | --------------------------------------- | ---------------------------- | -------------------------- |
222
+ | SIMPLE | step-3.7-flash (**FREE**) | gemini-2.5-flash ($0.30/$2.50) | kimi-k2.7 † ($0.95/$4.00) | gpt-4o-mini ($0.15/$0.60) |
223
+ | MEDIUM | gemini-3.1-flash-lite ($0.25/$1.50) | kimi-k2.7 † ($0.95/$4.00) | gpt-5.3-codex ($1.75/$14.00) | kimi-k2.7 † ($0.95/$4.00) |
224
+ | COMPLEX | gemini-3.1-flash-lite ($0.25/$1.50) | gemini-3.1-pro ($2/$12) | claude-fable-5 ($10/$50) | claude-sonnet-4.6 ($3/$15) |
225
+ | REASONING | grok-4-1-fast-reasoning † ($0.20/$0.50) | grok-4-1-fast-reasoning † ($0.20/$0.50) | claude-sonnet-4.6 ($3/$15) | claude-sonnet-4.6 ($3/$15) |
226
+
227
+ † Withheld from `/v1/models` — the router still calls it by direct ID, but you will not find it on the public pricing page. See [savings-mix.json](https://github.com/BlockRunAI/blockrun/blob/main/src/brand/savings-mix.json), which prices the published savings claim on visible models only.
228
+ ‡ Auto-selected in any profile when the turn actually needs its attached tools; prefers models that keep going instead of stopping to ask.
229
+
230
+ These are the curated primaries; every tier carries a benchmark-ordered fallback chain — full chains and per-profile ranking weights in [docs/routing-profiles.md](docs/routing-profiles.md). On router-core's frozen three-arm agent benchmark (τ-bench, BrowseComp, Terminal-Bench) the V3.4 policy completed **57%** of tasks vs **49%** for the previous rules router, at **6.4%** lower cost per successful task — and spent **8.9%** of the tokens a pinned flagship would have.
220
231
 
221
232
  **<!-- br:savings.autoVsBaselinePct -->88<!-- /br:savings.autoVsBaselinePct -->% cheaper than pinning Claude Opus 5** for the same traffic, on `auto`; **<!-- br:savings.ecoVsBaselinePct -->98<!-- /br:savings.ecoVsBaselinePct -->%** on `eco`.
222
233
 
@@ -227,6 +238,8 @@ answer. Models withheld from `/v1/models` are excluded from the mix — pricing
227
238
  public claim on a model you cannot look up is not defensible — which makes the
228
239
  number conservative.
229
240
 
241
+ Rollback lever: `routing.strategy: "rules"` restores the V2 primary-first selector; `routing.shadow` compares both locally without a second paid call.
242
+
230
243
  ---
231
244
 
232
245
  ## Image Generation
@@ -434,7 +447,6 @@ No Surf account, no API key — settles directly to Surf's Base treasury in USDC
434
447
  | google/gemini-3-flash-preview | $0.50 | $3.00 | $0.0018 | 1M | vision |
435
448
  | moonshot/kimi-k2.5 | $0.60 | $3.00 | $0.0018 | 262K | reasoning, vision, agentic, tools |
436
449
  | moonshot/kimi-k2.7 | $0.95 | $4.00 | $0.0025 | 262K | reasoning, vision, agentic, tools |
437
- | moonshot/kimi-k3 | $3.00 | $15.00 | $0.0110 | 1M | reasoning, vision, agentic, tools |
438
450
 
439
451
  ### Mid-Range Models ($0.001–$0.01/request)
440
452
 
@@ -478,13 +490,14 @@ No Surf account, no API key — settles directly to Surf's Base treasury in USDC
478
490
  | openai/gpt-5.6-sol | $5.00 | $30.00 | $0.0175 | 1M | reasoning, vision, agentic, tools |
479
491
  | openai/gpt-5.6-sol-pro | $5.00 | $30.00 | $0.0175 | 1M | reasoning, vision, agentic, tools |
480
492
  | openai/gpt-5.5 | $5.00 | $30.00 | $0.0175 | 1M | reasoning, vision, agentic, tools |
493
+ | moonshot/kimi-k3 | $3.00 | $15.00 | $0.0110 | 1M | reasoning, vision, agentic, tools |
481
494
  | openai/chat-latest | $5.00 | $30.00 | $0.0175 | 128K | vision, tools |
482
495
  | openai/o1 | $15.00 | $60.00 | $0.0375 | 200K | reasoning, tools |
483
496
  | openai/gpt-5.2-pro | $21.00 | $168.00 | $0.0945 | 400K | reasoning, tools |
484
497
  | openai/gpt-5.4-pro | $30.00 | $180.00 | $0.1050 | 400K | reasoning, tools |
485
498
  | openai/gpt-5.5-pro | $30.00 | $180.00 | $0.1050 | 1M | reasoning, vision, tools |
486
499
 
487
- > **Free tier:** several NVIDIA-hosted models cost nothing — `/model free` smart-routes across them, or pick one directly (e.g., `/model nemotron-omni` for vision, `/model step-flash` for reasoning, `/model mistral-nemotron` for instruction following).
500
+ > **Free tier:** <!-- br:models.free -->5<!-- /br:models.free --> NVIDIA-hosted models cost nothing — `/model free` pins the free default (`step-3.7-flash`, with the other four as fallbacks), `/model eco` opens on it, or pick one directly (e.g., `/model nemotron-omni` for vision, `/model step-flash` for reasoning, `/model mistral-nemotron` for instruction following).
488
501
  > **Best value:** `gpt-5-nano` and `gemini-2.5-flash-lite` deliver strong results at ~$0.0003/request.
489
502
 
490
503
  ---
@@ -700,7 +713,7 @@ Python plugin that wraps the ClawRouter proxy for `hermes-agent`. Same <!-- br:m
700
713
  | [Documentation](https://blockrun.ai/docs) | Full docs |
701
714
  | [Model Pricing](https://blockrun.ai/models) | All models & prices |
702
715
  | [Image Generation & Editing](docs/image-generation.md) | API examples, <!-- br:models.image -->9<!-- /br:models.image --> models |
703
- | [Routing Profiles](docs/routing-profiles.md) | ECO/AUTO/PREMIUM details |
716
+ | [Routing Profiles](docs/routing-profiles.md) | ECO/AUTO/PREMIUM/AGENTIC tiers, fallback chains, ranking weights |
704
717
  | [Architecture](docs/architecture.md) | Technical deep dive |
705
718
  | [Configuration](docs/configuration.md) | Environment variables |
706
719
  | [Troubleshooting](docs/troubleshooting.md) | Common issues |
package/dist/cli.js CHANGED
@@ -36894,12 +36894,16 @@ var init_models = __esm({
36894
36894
  "xai/grok-3-fast": "xai/grok-4-fast-reasoning",
36895
36895
  // delisted (too expensive)
36896
36896
  // NVIDIA — backward compat aliases (nvidia/xxx → free/xxx)
36897
- // Default free model is gpt-oss-120b (heavy user demand). New free models
36898
- // added 2026-04-29 — deepseek-v4-pro/flash, nemotron-omni — are additions,
36899
- // not replacements. Retired-with-redirect entries below mirror BlockRun
36900
- // server-side decommissioning of slow models (nemotron family, etc.).
36901
- nvidia: "free/gpt-oss-120b",
36897
+ // Default free model is step-3.7-flash — the same model @blockrun/router-core
36898
+ // opens the eco SIMPLE tier on. It replaced gpt-oss-120b on 2026-08-29:
36899
+ // gpt-oss-120b went dead upstream on 2026-08-16 (NVIDIA still LISTS it, but a
36900
+ // completion hangs until the client gives up — blockrun #391 retargeted its
36901
+ // whole free cascade off it, and the gateway now answers 400 Unknown model
36902
+ // for the `free/` id). Pins that NAME gpt-oss stay routable below — the
36903
+ // gateway server-redirects them — but nothing generic may land on it.
36904
+ nvidia: "free/step-3.7-flash",
36902
36905
  "gpt-120b": "free/gpt-oss-120b",
36906
+ // names the model itself — gateway redirects
36903
36907
  "gpt-20b": "free/gpt-oss-20b",
36904
36908
  "nvidia/gpt-oss-120b": "free/gpt-oss-120b",
36905
36909
  "nvidia/gpt-oss-20b": "free/gpt-oss-20b",
@@ -36974,9 +36978,10 @@ var init_models = __esm({
36974
36978
  // no live free Llama left (maverick died 2026-07)
36975
36979
  // qwen3-coder-480b retired 2026-06-14 → seed-oss-36b, which then EOL'd 2026-08-03.
36976
36980
  // Follow the gateway's own retarget rather than chaining to a second dead model.
36977
- "qwen-coder": "free/gpt-oss-120b",
36978
- "qwen-coder-free": "free/gpt-oss-120b",
36979
- "qwen-thinking": "free/gpt-oss-120b",
36981
+ "qwen-coder": "free/step-3.7-flash",
36982
+ // no live free Qwen; follows the free default
36983
+ "qwen-coder-free": "free/step-3.7-flash",
36984
+ "qwen-thinking": "free/step-3.7-flash",
36980
36985
  // qwen3-next died 2026-07-17; no live free Qwen left
36981
36986
  "qwen3-next": "free/qwen3-next-80b-a3b-instruct",
36982
36987
  // explicit-ish pin — gateway redirects
@@ -36987,8 +36992,8 @@ var init_models = __esm({
36987
36992
  // seed-oss pins name the model itself — kept routable, the gateway redirects them.
36988
36993
  "seed-oss": "free/seed-oss-36b",
36989
36994
  "seed-oss-36b": "free/seed-oss-36b",
36990
- "coder-free": "free/gpt-oss-120b",
36991
- // generic "a free coder" → follows the gateway retarget
36995
+ "coder-free": "free/step-3.7-flash",
36996
+ // generic "a free coder" → follows the free default
36992
36997
  "mistral-nemotron": "free/mistral-nemotron",
36993
36998
  "step-flash": "free/step-3.7-flash",
36994
36999
  "step-3.7-flash": "free/step-3.7-flash",
@@ -37000,21 +37005,25 @@ var init_models = __esm({
37000
37005
  "nemotron-omni": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
37001
37006
  "nano-omni": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
37002
37007
  "vision-free": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
37003
- // Retired shorthand aliases redirect to live successors (2026-07-17 map:
37004
- // llama-4-maverick died, so the old catch-all target moved to gpt-oss-120b)
37008
+ // Retired shorthand aliases redirect to live successors. The catch-all target
37009
+ // moved llama-4-maverick → gpt-oss-120b (2026-07-17) → step-3.7-flash
37010
+ // (2026-08-29, gpt-oss-120b hung upstream; see the NVIDIA block above).
37005
37011
  nemotron: "free/nemotron-3-nano-omni-30b-a3b-reasoning",
37006
37012
  // strongest live Nemotron
37007
- "nemotron-ultra": "free/gpt-oss-120b",
37008
- "nemotron-253b": "free/gpt-oss-120b",
37009
- "nemotron-super": "free/gpt-oss-120b",
37010
- "nemotron-49b": "free/gpt-oss-120b",
37011
- "nemotron-120b": "free/gpt-oss-120b",
37012
- devstral: "free/gpt-oss-120b",
37013
- // seed-oss-36b EOL'd 2026-08-03; matches blockrun's own retarget
37014
- "devstral-2": "free/gpt-oss-120b",
37013
+ "nemotron-ultra": "free/step-3.7-flash",
37014
+ "nemotron-253b": "free/step-3.7-flash",
37015
+ "nemotron-super": "free/step-3.7-flash",
37016
+ "nemotron-49b": "free/step-3.7-flash",
37017
+ "nemotron-120b": "free/step-3.7-flash",
37018
+ devstral: "free/step-3.7-flash",
37019
+ // seed-oss-36b EOL'd 2026-08-03
37020
+ "devstral-2": "free/step-3.7-flash",
37015
37021
  maverick: "free/llama-4-maverick",
37016
37022
  // explicit-ish pin — gateway redirects
37017
- free: "free/gpt-oss-120b",
37023
+ // `free` = the free-tier default. Must equal router-core's ecoTiers.SIMPLE
37024
+ // primary and the head of proxy.ts FREE_MODELS so `/model free`, the eco
37025
+ // profile and the budget-cap free fallback all agree on one live model.
37026
+ free: "free/step-3.7-flash",
37018
37027
  // MiniMax (minimax → current flagship: M3)
37019
37028
  minimax: "minimax/minimax-m3",
37020
37029
  "minimax-m3": "minimax/minimax-m3",
@@ -37084,7 +37093,7 @@ var init_models = __esm({
37084
37093
  },
37085
37094
  {
37086
37095
  id: "free",
37087
- name: "Free \u2192 GPT-OSS 120B",
37096
+ name: "Free \u2192 Step 3.7 Flash",
37088
37097
  inputPrice: 0,
37089
37098
  outputPrice: 0,
37090
37099
  contextWindow: 131072,
@@ -89548,7 +89557,15 @@ async function startProxy(options) {
89548
89557
  }
89549
89558
  if (full) {
89550
89559
  try {
89551
- const balanceInfo = await balanceMonitor.checkBalance();
89560
+ const balanceInfo = await Promise.race([
89561
+ balanceMonitor.checkBalance(),
89562
+ new Promise(
89563
+ (_, reject) => setTimeout(
89564
+ () => reject(new Error("balance check timed out")),
89565
+ BALANCE_CHECK_TIMEOUT_MS
89566
+ ).unref()
89567
+ )
89568
+ ]);
89552
89569
  response.balance = balanceInfo.balanceUSD;
89553
89570
  response.isLow = balanceInfo.isLow;
89554
89571
  response.isEmpty = balanceInfo.isEmpty;
@@ -92825,20 +92842,18 @@ var init_proxy = __esm({
92825
92842
  "premium"
92826
92843
  ]);
92827
92844
  FREE_MODELS = /* @__PURE__ */ new Set([
92828
- "free/gpt-oss-120b",
92829
- "free/gpt-oss-20b",
92830
- "free/mistral-nemotron",
92831
- // strong instruction following
92832
92845
  "free/step-3.7-flash",
92833
- // reasoning-focused
92846
+ // reasoning-focused — free-tier flagship
92834
92847
  "free/nemotron-nano-9b-v2",
92835
- // fast lightweight generalist
92848
+ // fast lightweight generalist (~0.7s)
92849
+ "free/mistral-nemotron",
92850
+ // strong instruction following
92836
92851
  "free/nemotron-3-nano-omni-30b-a3b-reasoning",
92837
92852
  // vision (text/image/video/audio)
92838
92853
  "free/nemotron-nano-12b-v2-vl"
92839
92854
  // vision-language (text + image)
92840
92855
  ]);
92841
- FREE_MODEL = "free/gpt-oss-120b";
92856
+ FREE_MODEL = "free/step-3.7-flash";
92842
92857
  MAX_MESSAGES = 200;
92843
92858
  CONTEXT_LIMIT_KB = 5120;
92844
92859
  HEARTBEAT_INTERVAL_MS = 2e3;
package/dist/index.js CHANGED
@@ -409,12 +409,16 @@ var init_models = __esm({
409
409
  "xai/grok-3-fast": "xai/grok-4-fast-reasoning",
410
410
  // delisted (too expensive)
411
411
  // NVIDIA — backward compat aliases (nvidia/xxx → free/xxx)
412
- // Default free model is gpt-oss-120b (heavy user demand). New free models
413
- // added 2026-04-29 — deepseek-v4-pro/flash, nemotron-omni — are additions,
414
- // not replacements. Retired-with-redirect entries below mirror BlockRun
415
- // server-side decommissioning of slow models (nemotron family, etc.).
416
- nvidia: "free/gpt-oss-120b",
412
+ // Default free model is step-3.7-flash — the same model @blockrun/router-core
413
+ // opens the eco SIMPLE tier on. It replaced gpt-oss-120b on 2026-08-29:
414
+ // gpt-oss-120b went dead upstream on 2026-08-16 (NVIDIA still LISTS it, but a
415
+ // completion hangs until the client gives up — blockrun #391 retargeted its
416
+ // whole free cascade off it, and the gateway now answers 400 Unknown model
417
+ // for the `free/` id). Pins that NAME gpt-oss stay routable below — the
418
+ // gateway server-redirects them — but nothing generic may land on it.
419
+ nvidia: "free/step-3.7-flash",
417
420
  "gpt-120b": "free/gpt-oss-120b",
421
+ // names the model itself — gateway redirects
418
422
  "gpt-20b": "free/gpt-oss-20b",
419
423
  "nvidia/gpt-oss-120b": "free/gpt-oss-120b",
420
424
  "nvidia/gpt-oss-20b": "free/gpt-oss-20b",
@@ -489,9 +493,10 @@ var init_models = __esm({
489
493
  // no live free Llama left (maverick died 2026-07)
490
494
  // qwen3-coder-480b retired 2026-06-14 → seed-oss-36b, which then EOL'd 2026-08-03.
491
495
  // Follow the gateway's own retarget rather than chaining to a second dead model.
492
- "qwen-coder": "free/gpt-oss-120b",
493
- "qwen-coder-free": "free/gpt-oss-120b",
494
- "qwen-thinking": "free/gpt-oss-120b",
496
+ "qwen-coder": "free/step-3.7-flash",
497
+ // no live free Qwen; follows the free default
498
+ "qwen-coder-free": "free/step-3.7-flash",
499
+ "qwen-thinking": "free/step-3.7-flash",
495
500
  // qwen3-next died 2026-07-17; no live free Qwen left
496
501
  "qwen3-next": "free/qwen3-next-80b-a3b-instruct",
497
502
  // explicit-ish pin — gateway redirects
@@ -502,8 +507,8 @@ var init_models = __esm({
502
507
  // seed-oss pins name the model itself — kept routable, the gateway redirects them.
503
508
  "seed-oss": "free/seed-oss-36b",
504
509
  "seed-oss-36b": "free/seed-oss-36b",
505
- "coder-free": "free/gpt-oss-120b",
506
- // generic "a free coder" → follows the gateway retarget
510
+ "coder-free": "free/step-3.7-flash",
511
+ // generic "a free coder" → follows the free default
507
512
  "mistral-nemotron": "free/mistral-nemotron",
508
513
  "step-flash": "free/step-3.7-flash",
509
514
  "step-3.7-flash": "free/step-3.7-flash",
@@ -515,21 +520,25 @@ var init_models = __esm({
515
520
  "nemotron-omni": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
516
521
  "nano-omni": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
517
522
  "vision-free": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
518
- // Retired shorthand aliases redirect to live successors (2026-07-17 map:
519
- // llama-4-maverick died, so the old catch-all target moved to gpt-oss-120b)
523
+ // Retired shorthand aliases redirect to live successors. The catch-all target
524
+ // moved llama-4-maverick → gpt-oss-120b (2026-07-17) → step-3.7-flash
525
+ // (2026-08-29, gpt-oss-120b hung upstream; see the NVIDIA block above).
520
526
  nemotron: "free/nemotron-3-nano-omni-30b-a3b-reasoning",
521
527
  // strongest live Nemotron
522
- "nemotron-ultra": "free/gpt-oss-120b",
523
- "nemotron-253b": "free/gpt-oss-120b",
524
- "nemotron-super": "free/gpt-oss-120b",
525
- "nemotron-49b": "free/gpt-oss-120b",
526
- "nemotron-120b": "free/gpt-oss-120b",
527
- devstral: "free/gpt-oss-120b",
528
- // seed-oss-36b EOL'd 2026-08-03; matches blockrun's own retarget
529
- "devstral-2": "free/gpt-oss-120b",
528
+ "nemotron-ultra": "free/step-3.7-flash",
529
+ "nemotron-253b": "free/step-3.7-flash",
530
+ "nemotron-super": "free/step-3.7-flash",
531
+ "nemotron-49b": "free/step-3.7-flash",
532
+ "nemotron-120b": "free/step-3.7-flash",
533
+ devstral: "free/step-3.7-flash",
534
+ // seed-oss-36b EOL'd 2026-08-03
535
+ "devstral-2": "free/step-3.7-flash",
530
536
  maverick: "free/llama-4-maverick",
531
537
  // explicit-ish pin — gateway redirects
532
- free: "free/gpt-oss-120b",
538
+ // `free` = the free-tier default. Must equal router-core's ecoTiers.SIMPLE
539
+ // primary and the head of proxy.ts FREE_MODELS so `/model free`, the eco
540
+ // profile and the budget-cap free fallback all agree on one live model.
541
+ free: "free/step-3.7-flash",
533
542
  // MiniMax (minimax → current flagship: M3)
534
543
  minimax: "minimax/minimax-m3",
535
544
  "minimax-m3": "minimax/minimax-m3",
@@ -599,7 +608,7 @@ var init_models = __esm({
599
608
  },
600
609
  {
601
610
  id: "free",
602
- name: "Free \u2192 GPT-OSS 120B",
611
+ name: "Free \u2192 Step 3.7 Flash",
603
612
  inputPrice: 0,
604
613
  outputPrice: 0,
605
614
  contextWindow: 131072,
@@ -89368,7 +89377,15 @@ async function startProxy(options) {
89368
89377
  }
89369
89378
  if (full) {
89370
89379
  try {
89371
- const balanceInfo = await balanceMonitor.checkBalance();
89380
+ const balanceInfo = await Promise.race([
89381
+ balanceMonitor.checkBalance(),
89382
+ new Promise(
89383
+ (_, reject) => setTimeout(
89384
+ () => reject(new Error("balance check timed out")),
89385
+ BALANCE_CHECK_TIMEOUT_MS
89386
+ ).unref()
89387
+ )
89388
+ ]);
89372
89389
  response.balance = balanceInfo.balanceUSD;
89373
89390
  response.isLow = balanceInfo.isLow;
89374
89391
  response.isEmpty = balanceInfo.isEmpty;
@@ -92645,20 +92662,18 @@ var init_proxy = __esm({
92645
92662
  "premium"
92646
92663
  ]);
92647
92664
  FREE_MODELS = /* @__PURE__ */ new Set([
92648
- "free/gpt-oss-120b",
92649
- "free/gpt-oss-20b",
92650
- "free/mistral-nemotron",
92651
- // strong instruction following
92652
92665
  "free/step-3.7-flash",
92653
- // reasoning-focused
92666
+ // reasoning-focused — free-tier flagship
92654
92667
  "free/nemotron-nano-9b-v2",
92655
- // fast lightweight generalist
92668
+ // fast lightweight generalist (~0.7s)
92669
+ "free/mistral-nemotron",
92670
+ // strong instruction following
92656
92671
  "free/nemotron-3-nano-omni-30b-a3b-reasoning",
92657
92672
  // vision (text/image/video/audio)
92658
92673
  "free/nemotron-nano-12b-v2-vl"
92659
92674
  // vision-language (text + image)
92660
92675
  ]);
92661
- FREE_MODEL = "free/gpt-oss-120b";
92676
+ FREE_MODEL = "free/step-3.7-flash";
92662
92677
  MAX_MESSAGES = 200;
92663
92678
  CONTEXT_LIMIT_KB = 5120;
92664
92679
  HEARTBEAT_INTERVAL_MS = 2e3;
@@ -96,16 +96,28 @@ if (inflight) {
96
96
  // Extract user's last message
97
97
  const prompt = messages.findLast((m) => m.role === "user")?.content;
98
98
 
99
- // Run 15-dimension weighted scorer
99
+ // Router Core V3.4 (@blockrun/router-core): 15-dimension scorer → hard
100
+ // capability filters → portfolio ranking. Model capabilities come from the
101
+ // live catalog, injected at proxy startup.
100
102
  const decision = route(prompt, systemPrompt, maxTokens, {
101
103
  config: DEFAULT_ROUTING_CONFIG,
102
104
  modelPricing,
105
+ modelCapabilities,
106
+ routingProfile: "auto",
107
+ hasTools,
108
+ toolCount,
109
+ toolNames,
110
+ hasVision,
103
111
  });
104
112
 
105
113
  // decision = {
106
114
  // model: "google/gemini-2.5-flash",
107
115
  // tier: "SIMPLE",
116
+ // taskType: "chat",
108
117
  // confidence: 0.92,
118
+ // method: "portfolio",
119
+ // routerVersion: "v3-portfolio",
120
+ // candidates: ["google/gemini-2.5-flash", "google/gemini-3-flash-preview", ...],
109
121
  // savings: 0.99,
110
122
  // costEstimate: 0.0012,
111
123
  // }
@@ -235,17 +247,12 @@ data: [DONE]
235
247
 
236
248
  ## Routing Engine
237
249
 
238
- ### Weighted Scorer
250
+ The routing engine lives in [`@blockrun/router-core`](https://github.com/BlockRunAI/router-core) (Router Core V3.4), a product-neutral package shared by ClawRouter, Franklin, the `@blockrun/llm` SDKs and ClawRouter-Hermes. `src/router/index.ts` is a single `export * from "@blockrun/router-core"`; the package is a `devDependency` inlined by tsup at build time and pinned to an immutable commit SHA. Nothing in the decision path touches the network.
239
251
 
240
- The routing engine uses a 15-dimension weighted scorer that runs entirely locally:
252
+ ### 1. Classify — 15-dimension weighted scorer
241
253
 
242
254
  ```typescript
243
- function classifyByRules(
244
- prompt: string,
245
- systemPrompt: string | undefined,
246
- tokenCount: number,
247
- config: ScoringConfig,
248
- ): ClassificationResult {
255
+ function classifyByRules(prompt, systemPrompt, tokenCount, config): ClassificationResult {
249
256
  let score = 0;
250
257
  const signals: string[] = [];
251
258
 
@@ -262,51 +269,60 @@ function classifyByRules(
262
269
  signals.push("code");
263
270
  }
264
271
 
265
- // ... 13 more dimensions
266
-
267
- // Sigmoid calibration
268
- const confidence = sigmoid(score, (k = 8), (midpoint = 0.5));
272
+ // ... 13 more dimensions (multiStepPatterns, technicalTerms, tokenCount,
273
+ // creativeMarkers, questionComplexity, constraintCount, agenticTask, ...)
269
274
 
275
+ // Sigmoid calibration (steepness 12), ambiguous below 0.7
276
+ const confidence = sigmoid(score, config.confidenceSteepness);
270
277
  return { score, confidence, tier: selectTier(score, confidence), signals };
271
278
  }
272
279
  ```
273
280
 
274
- ### Tier Selection
281
+ Tier boundaries: `< 0.3` SIMPLE, `< 0.5` COMPLEX, else REASONING (2+ reasoning markers short-circuit to REASONING). Alongside the tier, a task classifier derives the _shape_ of the work from the prompt, the visible tool names/count, requested output size and language: `chat`, `extraction`, `code_edit`, `code_agent`, `tool_agent`, `tool_agent_parallel`, `debug`, `reasoning`, `reasoning_mcq`, `reasoning_math`, `long_context`, `vision`.
275
282
 
276
- ```typescript
277
- function selectTier(score: number, confidence: number): Tier | null {
278
- // Special case: 2+ reasoning markers → REASONING at high confidence
279
- if (signals.includes("reasoning") && reasoningCount >= 2) {
280
- return "REASONING";
281
- }
283
+ ### 2. Filter — hard eligibility
282
284
 
283
- if (confidence < 0.7) {
284
- return null; // Ambiguous → default to MEDIUM
285
- }
285
+ The tier's curated chain (primary + fallbacks) is the candidate pool. Before anything is scored, candidates are removed that:
286
286
 
287
- if (score < 0.3) return "SIMPLE";
288
- if (score < 0.6) return "MEDIUM";
289
- if (score < 0.8) return "COMPLEX";
290
- return "REASONING";
291
- }
292
- ```
287
+ - lack tool calling on a turn that requires tools (`inferToolRequirement` — `tool_choice: "none"` is authoritative; host tool descriptions alone never create a requirement)
288
+ - lack vision on image input
289
+ - have too small a context window for the conversation, or too small a max-output for the requested length
290
+ - take an incompatible structured-output path
291
+ - are absent from the live catalog injected by the proxy (`modelCapabilities`)
293
292
 
294
- ### Overrides
293
+ Capability errors never reach the preference stage — the router fails closed rather than optimistically cheap.
295
294
 
296
- Certain conditions force tier assignment:
295
+ ### 3. Rank — portfolio scoring
296
+
297
+ Survivors are scored on six bounded factors with per-profile weights (auto: quality 0.47 · capability 0.20 · cost 0.18 · speed 0.07 · reliability 0.03 · curated order 0.05; eco raises cost to 0.28, premium raises quality to 0.58). High-stakes turns boost quality and reliability, latency-sensitive turns boost speed; an `affinityFloorGap` stops a candidate far below the best task affinity from winning on price. Speed and reliability priors come from `model-profiles.generated.json` (BlockRun's gateway benchmark), decayed on a 30-day half-life.
298
+
299
+ ### 4. Recover — the fallback chain
300
+
301
+ The full ranked list is returned as `decision.candidates`; the proxy walks it on timeouts and 5xx. The winner is chosen once per request — no mid-task drift, no auxiliary routing call.
302
+
303
+ ### Overrides
297
304
 
298
305
  ```typescript
299
306
  // Large context → COMPLEX
300
- if (tokenCount > 100000) {
307
+ if (tokenCount > config.overrides.maxTokensForceComplex /* 100_000 */) {
301
308
  return { tier: "COMPLEX", method: "override:large_context" };
302
309
  }
303
310
 
304
- // Structured output (JSON/YAML) → min MEDIUM
305
- if (systemPrompt?.includes("json") || systemPrompt?.includes("yaml")) {
306
- return { tier: Math.max(tier, "MEDIUM"), method: "override:structured" };
311
+ // Structured output (JSON/YAML) → at least MEDIUM
312
+ if (requiresStructuredOutput) {
313
+ return {
314
+ tier: max(tier, config.overrides.structuredOutputMinTier),
315
+ method: "override:structured",
316
+ };
307
317
  }
308
318
  ```
309
319
 
320
+ ### Escape hatches
321
+
322
+ - `routing.strategy = "rules"` — one-line rollback to the V2 primary-first selector.
323
+ - `routing.shadow = { strategy: "rules", sampleRate }` — recompute a comparison decision locally; reported on debug headers, never a second paid call.
324
+ - `unavailableModels` — the host can hard-remove models it observed dead at the gateway from every chain before selection (router-core API; not yet wired in the proxy — free-model liveness is enforced at build time by `src/router/free-model-liveness.test.ts` instead).
325
+
310
326
  ---
311
327
 
312
328
  ## Payment System
@@ -538,22 +554,20 @@ src/
538
554
  ├── retry.ts # Fetch retry with exponential backoff
539
555
  ├── version.ts # Version from package.json
540
556
  └── router/
541
- ├── index.ts # route() entry point
542
- ├── rules.ts # 15-dimension weighted scorer (9-language)
543
- ├── selector.ts # Tier → model selection + fallback
544
- ├── config.ts # Default routing configuration (ECO/AUTO/PREMIUM/AGENTIC)
545
- └── types.ts # TypeScript type definitions
557
+ ├── index.ts # export * from "@blockrun/router-core" (Router Core V3.4)
558
+ ├── free-model-liveness.test.ts # build-time guard: no chain names a dead free model
559
+ └── brand-numbers.test.ts # README/SKILL brand markers stay in sync
546
560
  ```
547
561
 
548
562
  ### Key Files
549
563
 
550
- | File | Purpose |
551
- | -------------------- | ------------------------------------------------------------- |
552
- | `proxy.ts` | Core request handling, SSE simulation, fallback chain |
553
- | `wallet.ts` | BIP-39 mnemonic generation, EVM + Solana (SLIP-10) derivation |
554
- | `router/rules.ts` | 15-dimension weighted scorer, 9-language keyword sets |
555
- | `x402.ts` | EIP-712 typed data signing, payment header formatting |
556
- | `balance.ts` | USDC balance via Base RPC (EVM), caching, thresholds |
557
- | `solana-balance.ts` | USDC balance via Solana RPC (SPL Token), caching, retries |
558
- | `payment-preauth.ts` | Pre-authorization cache (EVM; skipped for Solana) |
559
- | `dedup.ts` | SHA-256 hashing, 30s response cache |
564
+ | File | Purpose |
565
+ | -------------------- | ----------------------------------------------------------------------------------- |
566
+ | `proxy.ts` | Core request handling, SSE simulation, fallback chain |
567
+ | `wallet.ts` | BIP-39 mnemonic generation, EVM + Solana (SLIP-10) derivation |
568
+ | `router/index.ts` | Re-exports `@blockrun/router-core` (scorer, filters, portfolio ranker, tier config) |
569
+ | `x402.ts` | EIP-712 typed data signing, payment header formatting |
570
+ | `balance.ts` | USDC balance via Base RPC (EVM), caching, thresholds |
571
+ | `solana-balance.ts` | USDC balance via Solana RPC (SPL Token), caching, retries |
572
+ | `payment-preauth.ts` | Pre-authorization cache (EVM; skipped for Solana) |
573
+ | `dedup.ts` | SHA-256 hashing, 30s response cache |
@@ -307,12 +307,18 @@ const decision = route("Prove sqrt(2) is irrational", undefined, 4096, {
307
307
 
308
308
  console.log(decision);
309
309
  // {
310
- // model: "deepseek/deepseek-reasoner",
310
+ // model: "xai/grok-4-1-fast-reasoning",
311
311
  // tier: "REASONING",
312
+ // taskType: "reasoning_math",
312
313
  // confidence: 0.97,
313
- // method: "rules",
314
- // savings: 0.994,
315
- // costEstimate: 0.002,
314
+ // method: "portfolio",
315
+ // routerVersion: "v3-portfolio",
316
+ // profile: "auto",
317
+ // candidates: ["xai/grok-4-1-fast-reasoning", "xai/grok-4-fast-reasoning", "deepseek/deepseek-reasoner", ...],
318
+ // candidateScores: [{ model, score, quality, cost, speed, reliability }, ...],
319
+ // savings: 0.99,
320
+ // costEstimate: 0.0007,
321
+ // reasoning: "…",
316
322
  // }
317
323
  ```
318
324
 
@@ -354,6 +360,8 @@ const proxy = await startProxy({
354
360
 
355
361
  ## Routing Configuration
356
362
 
363
+ Routing decisions are made by [`@blockrun/router-core`](https://github.com/BlockRunAI/router-core) (Router Core V3.4). The `routing` block is merged over router-core's `DEFAULT_ROUTING_CONFIG`: tier maps are merged per tier (override just `COMPLEX` without redefining the other three), `classifier` / `scoring` / `overrides` are merged per key, and `null` disables a tier set.
364
+
357
365
  ### Via openclaw.yaml
358
366
 
359
367
  ```yaml
@@ -378,22 +386,33 @@ plugins:
378
386
  # Their cost is charged via x402 micropayment directly and is not tracked per-session.
379
387
 
380
388
  routing:
381
- # Override tier assignments
389
+ # Strategy. Default: portfolio (Router Core V3.4 — constraint-first ranking
390
+ # over the tier's chain). "rules" is the one-line rollback to the V2
391
+ # primary-first selector.
392
+ strategy: portfolio
393
+
394
+ # Optional shadow evaluation: recompute a comparison decision locally on a
395
+ # sample of requests and report it on the x-clawrouter-* debug headers.
396
+ # Never issues a second paid completion, never persists prompt content.
397
+ # shadow:
398
+ # strategy: rules
399
+ # sampleRate: 0.1
400
+
401
+ # Override tier chains (auto profile). Each tier is merged individually,
402
+ # so you can override just COMPLEX. Under the portfolio strategy the
403
+ # chain is the candidate pool: primary is the curated head, the ranker
404
+ # still enforces tool/vision/context constraints and may pick a fallback.
382
405
  tiers:
383
- SIMPLE:
384
- primary: "google/gemini-2.5-flash"
385
- fallback: ["deepseek/deepseek-chat"]
386
- MEDIUM:
387
- primary: "deepseek/deepseek-chat"
388
- fallback: ["openai/gpt-4o-mini"]
389
406
  COMPLEX:
390
- primary: "anthropic/claude-sonnet-4.6"
391
- fallback: ["openai/gpt-4o"]
392
- REASONING:
393
- primary: "deepseek/deepseek-reasoner"
394
- fallback: ["openai/o3-mini"]
407
+ primary: "anthropic/claude-sonnet-5"
408
+ fallback: ["google/gemini-3.1-pro", "openai/gpt-5.6-terra"]
409
+
410
+ # Same shape for the other tier sets:
411
+ # ecoTiers: { ... }
412
+ # premiumTiers: { ... }
413
+ # agenticTiers: { ... } # or `null` to disable agentic switching entirely
395
414
 
396
- # Override scoring parameters
415
+ # Override scoring keywords
397
416
  scoring:
398
417
  reasoningKeywords: ["prove", "theorem", "formal", "derive"]
399
418
  codeKeywords: ["function", "class", "async", "import"]
@@ -402,38 +421,41 @@ plugins:
402
421
  # Override thresholds
403
422
  classifier:
404
423
  confidenceThreshold: 0.7
405
- reasoningConfidence: 0.97
406
424
 
407
425
  # Context-based overrides
408
426
  overrides:
409
- largeContextTokens: 100000 # Force COMPLEX above this
410
- structuredOutput: true # Bump to min MEDIUM for JSON/YAML
427
+ maxTokensForceComplex: 100000 # Force COMPLEX above this many tokens
428
+ structuredOutputMinTier: MEDIUM # Bump to at least MEDIUM for JSON/YAML
429
+ ambiguousDefaultTier: MEDIUM # Where low-confidence requests land
430
+ # agenticMode: true | false # force / disable the agentic tier set (default: auto-detect)
411
431
  ```
412
432
 
413
433
  ---
414
434
 
415
435
  ## Tier Overrides
416
436
 
417
- ### Default Tier Mappings
437
+ ### Default Tier Mappings (auto profile)
438
+
439
+ Curated primaries from router-core's `DEFAULT_ROUTING_CONFIG.tiers`; chains truncated. The full chains for every profile — and the eco / premium / agentic tier sets — are in [routing-profiles.md](./routing-profiles.md).
418
440
 
419
- | Tier | Primary Model | Fallback Chain |
420
- | --------- | ----------------------------- | ----------------------------------------------- |
421
- | SIMPLE | `google/gemini-2.5-flash` | `deepseek/deepseek-chat` |
422
- | MEDIUM | `deepseek/deepseek-chat` | `openai/gpt-4o-mini`, `google/gemini-2.5-flash` |
423
- | COMPLEX | `anthropic/claude-sonnet-4.6` | `openai/gpt-4o`, `google/gemini-2.5-pro` |
424
- | REASONING | `deepseek/deepseek-reasoner` | `openai/o3-mini`, `anthropic/claude-sonnet-4.6` |
441
+ | Tier | Primary Model | Fallback Chain (head) |
442
+ | --------- | ----------------------------- | ------------------------------------------------------------ |
443
+ | SIMPLE | `google/gemini-2.5-flash` | `google/gemini-3-flash-preview`, `deepseek/deepseek-chat`, … |
444
+ | MEDIUM | `moonshot/kimi-k2.7` | `moonshot/kimi-k2.6`, `moonshot/kimi-k2.5`, … |
445
+ | COMPLEX | `google/gemini-3.1-pro` | `google/gemini-3-flash-preview`, `xai/grok-4-0709`, … |
446
+ | REASONING | `xai/grok-4-1-fast-reasoning` | `xai/grok-4-fast-reasoning`, `deepseek/deepseek-reasoner`, … |
425
447
 
426
448
  ### Fallback Chain
427
449
 
428
- When the primary model fails (rate limits, billing errors, provider outages), ClawRouter tries the next model in the fallback chain:
450
+ The ranked candidate list is returned on every decision (`decision.candidates`). When the selected model fails (rate limits, billing errors, provider outages, timeouts), ClawRouter tries the next candidate:
429
451
 
430
452
  ```
431
- Request → gemini-2.5-flash (rate limited)
432
- → deepseek-chat (billing error)
433
- → gpt-4o-mini (success)
453
+ Request → gemini-3.1-pro (503)
454
+ → gemini-3-flash-preview (rate limited)
455
+ → grok-4-0709 (success)
434
456
  ```
435
457
 
436
- Max fallback attempts: 3 models per request.
458
+ Candidates that fail a hard constraint (no tool calling on a tool turn, no vision on image input, too small a context window) are removed before ranking, so a fallback never lands on a model that cannot serve the request.
437
459
 
438
460
  ### Custom Tier Configuration
439
461
 
@@ -441,10 +463,10 @@ Max fallback attempts: 3 models per request.
441
463
  routing:
442
464
  tiers:
443
465
  COMPLEX:
444
- primary: "openai/gpt-4o" # Use GPT-4o instead of Claude
466
+ primary: "openai/gpt-5.6-terra" # Use GPT-5.6 Terra instead of Gemini 3.1 Pro
445
467
  fallback:
446
- - "anthropic/claude-sonnet-4.6"
447
- - "google/gemini-2.5-pro"
468
+ - "anthropic/claude-sonnet-5"
469
+ - "google/gemini-3.1-pro"
448
470
  ```
449
471
 
450
472
  ---
@@ -458,12 +480,12 @@ The 15-dimension weighted scorer determines query complexity:
458
480
  | `reasoningMarkers` | 0.18 | "prove", "theorem", "step by step" |
459
481
  | `codePresence` | 0.15 | "function", "async", "import", "```" |
460
482
  | `multiStepPatterns` | 0.12 | "first...then", "step 1", numbered lists |
461
- | `agenticTask` | 0.10 | "run", "test", "fix", "deploy", "edit" |
462
483
  | `technicalTerms` | 0.10 | "algorithm", "kubernetes", "distributed" |
463
484
  | `tokenCount` | 0.08 | short (<50) vs long (>500) |
464
485
  | `creativeMarkers` | 0.05 | "story", "poem", "brainstorm" |
465
486
  | `questionComplexity` | 0.05 | Multiple question marks |
466
487
  | `constraintCount` | 0.04 | "at most", "O(n)", "maximum" |
488
+ | `agenticTask` | 0.04 | "run", "test", "fix", "deploy", "edit" |
467
489
  | `imperativeVerbs` | 0.03 | "build", "create", "implement" |
468
490
  | `outputFormat` | 0.03 | "json", "yaml", "schema" |
469
491
  | `simpleIndicators` | 0.02 | "what is", "define", "translate" |
@@ -500,10 +522,12 @@ The classifier uses sigmoid calibration to convert raw scores to confidence valu
500
522
  confidence = 1 / (1 + exp(-k * (score - midpoint)))
501
523
  ```
502
524
 
503
- Parameters:
525
+ Parameters (router-core `classifier`):
504
526
 
505
- - `k = 8` — steepness of the sigmoid curve
506
- - `midpoint = 0.5` — score at which confidence = 50%
527
+ - `confidenceSteepness = 12` — steepness of the sigmoid curve
528
+ - `confidenceThreshold = 0.7` — below this the request is ambiguous and lands on `overrides.ambiguousDefaultTier` (MEDIUM)
529
+
530
+ Tier boundaries on the weighted-score axis: `mediumComplex = 0.3`, `complexReasoning = 0.5`.
507
531
 
508
532
  ### Override Thresholds
509
533
 
@@ -512,9 +536,6 @@ routing:
512
536
  classifier:
513
537
  # Require higher confidence for tier assignment
514
538
  confidenceThreshold: 0.8 # Default: 0.7
515
-
516
- # Force REASONING tier at lower confidence
517
- reasoningConfidence: 0.90 # Default: 0.97
518
539
  ```
519
540
 
520
541
  ---
@@ -51,17 +51,17 @@ The returned URL is a publicly hosted image, ready to use in Telegram, Discord,
51
51
 
52
52
  ## Models & Pricing
53
53
 
54
- | Model ID | Shorthand | Price | Sizes | Provider |
55
- | ---------------------------- | ------------------ | ------------------- | ---------------------------------------------------------------------------------- | --------------------- |
56
- | `google/nano-banana` | `nano-banana` | $0.05/image | 1024×1024 | Google Gemini Flash |
57
- | `google/nano-banana-2` | `banana-2` | $0.09/image | 1024×1024 | Google Nano Banana 2 |
58
- | `google/nano-banana-pro` | `banana-pro` | $0.10–$0.15/image | 1024×1024, 2048×2048, 4096×4096 | Google Gemini Pro |
59
- | `openai/gpt-image-1` | `gpt-image` | $0.02–$0.04/image | 1024×1024, 1536×1024, 1024×1536 | OpenAI GPT Image 1 |
60
- | `openai/gpt-image-2` | `gpt-image-2` | $0.06–$0.12/image | 1024×1024, 1536×1024, 1024×1536 | OpenAI GPT Image 2 |
61
- | `bytedance/seedream-5-pro` | `seedream` | $0.045–$0.09/image | 1024×1024, 1280×720, 2048×1024, 2048×2048, 2304×1728, 1728×2304, 2848×1600, 1600×2848 | ByteDance Seedream 5 |
62
- | `xai/grok-imagine-image` | `grok-imagine` | $0.02/image | 1024×1024 | xAI Grok Imagine |
63
- | `xai/grok-imagine-image-pro` | `grok-imagine-pro` | $0.07/image | 1024×1024 | xAI Grok Imagine Pro |
64
- | `zai/cogview-4` | `cogview` | $0.015–$0.02/image | 512×512, 768×768, 1024×1024, 768×1344, 1344×768, 1440×1440 | Zhipu CogView-4 |
54
+ | Model ID | Shorthand | Price | Sizes | Provider |
55
+ | ---------------------------- | ------------------ | ------------------ | ------------------------------------------------------------------------------------- | -------------------- |
56
+ | `google/nano-banana` | `nano-banana` | $0.05/image | 1024×1024 | Google Gemini Flash |
57
+ | `google/nano-banana-2` | `banana-2` | $0.09/image | 1024×1024 | Google Nano Banana 2 |
58
+ | `google/nano-banana-pro` | `banana-pro` | $0.10–$0.15/image | 1024×1024, 2048×2048, 4096×4096 | Google Gemini Pro |
59
+ | `openai/gpt-image-1` | `gpt-image` | $0.02–$0.04/image | 1024×1024, 1536×1024, 1024×1536 | OpenAI GPT Image 1 |
60
+ | `openai/gpt-image-2` | `gpt-image-2` | $0.06–$0.12/image | 1024×1024, 1536×1024, 1024×1536 | OpenAI GPT Image 2 |
61
+ | `bytedance/seedream-5-pro` | `seedream` | $0.045–$0.09/image | 1024×1024, 1280×720, 2048×1024, 2048×2048, 2304×1728, 1728×2304, 2848×1600, 1600×2848 | ByteDance Seedream 5 |
62
+ | `xai/grok-imagine-image` | `grok-imagine` | $0.02/image | 1024×1024 | xAI Grok Imagine |
63
+ | `xai/grok-imagine-image-pro` | `grok-imagine-pro` | $0.07/image | 1024×1024 | xAI Grok Imagine Pro |
64
+ | `zai/cogview-4` | `cogview` | $0.015–$0.02/image | 512×512, 768×768, 1024×1024, 768×1344, 1344×768, 1440×1440 | Zhipu CogView-4 |
65
65
 
66
66
  Default model: `google/nano-banana`.
67
67
 
@@ -369,18 +369,18 @@ When using ClawRouter with OpenClaw, generate and edit images directly from any
369
369
 
370
370
  ### Model shorthands
371
371
 
372
- | Shorthand | Full ID |
373
- | ------------------------------------ | ---------------------------- |
374
- | `nano-banana`, `banana` | `google/nano-banana` |
375
- | `banana-2`, `nano-banana-2` | `google/nano-banana-2` |
376
- | `banana-pro`, `nano-banana-pro` | `google/nano-banana-pro` |
377
- | `gpt-image`, `gpt-image-1` | `openai/gpt-image-1` |
378
- | `gpt-image-2` | `openai/gpt-image-2` |
379
- | `seedream` | `bytedance/seedream-5-pro` |
380
- | `grok-imagine` | `xai/grok-imagine-image` |
381
- | `grok-imagine-pro` | `xai/grok-imagine-image-pro` |
382
- | `cogview` | `zai/cogview-4` |
383
- | `dall-e-3`, `dalle3`, `dalle` (legacy) | `openai/gpt-image-2` |
372
+ | Shorthand | Full ID |
373
+ | -------------------------------------- | ---------------------------- |
374
+ | `nano-banana`, `banana` | `google/nano-banana` |
375
+ | `banana-2`, `nano-banana-2` | `google/nano-banana-2` |
376
+ | `banana-pro`, `nano-banana-pro` | `google/nano-banana-pro` |
377
+ | `gpt-image`, `gpt-image-1` | `openai/gpt-image-1` |
378
+ | `gpt-image-2` | `openai/gpt-image-2` |
379
+ | `seedream` | `bytedance/seedream-5-pro` |
380
+ | `grok-imagine` | `xai/grok-imagine-image` |
381
+ | `grok-imagine-pro` | `xai/grok-imagine-image-pro` |
382
+ | `cogview` | `zai/cogview-4` |
383
+ | `dall-e-3`, `dalle3`, `dalle` (legacy) | `openai/gpt-image-2` |
384
384
 
385
385
  ---
386
386
 
@@ -1,62 +1,106 @@
1
1
  # Routing Profiles & Pricing
2
2
 
3
- ClawRouter offers four routing profiles to balance cost vs quality. Prices are in **$/M tokens** (input/output). Tables show each tier's **primary** model — every tier also carries a benchmark-ordered fallback chain (see `src/router/config.ts`).
3
+ ClawRouter offers four routing profiles to balance cost vs quality. Prices are in **$/M tokens** (input/output), taken from `src/models.ts` (which mirrors the live BlockRun catalog).
4
4
 
5
- ## ECO (Absolute Cheapest)
5
+ Routing decisions are made by [`@blockrun/router-core`](https://github.com/BlockRunAI/router-core) (Router Core **V3.4**, the constraint-first portfolio router), which ClawRouter inlines at build time and pins by commit SHA. `src/router/index.ts` simply re-exports it. Nothing below calls a network or a second model: classification, eligibility filtering and ranking all run locally in about a quarter of a millisecond.
6
+
7
+ ## How a request is routed
8
+
9
+ 1. **Classify.** A 15-dimension weighted scorer maps the request onto a capability tier — `SIMPLE`, `MEDIUM`, `COMPLEX` or `REASONING` — and a task classifier labels the _shape_ of the work (`chat`, `extraction`, `code_edit`, `code_agent`, `tool_agent`, `tool_agent_parallel`, `debug`, `reasoning`, `reasoning_math`, `long_context`, `vision`, …). Turns that actually need their attached tools switch to the **agentic** tier set automatically.
10
+ 2. **Filter.** The tier's curated chain (primary + fallbacks, below) is the candidate pool. Every model that cannot satisfy the request is removed **before** scoring: no tool calling on a tool-required turn, no vision on image input, too small a context window, too small a max-output, an incompatible structured-output path, or absent from the live catalog. Being cheap never compensates for failing the contract.
11
+ 3. **Rank.** Survivors are scored on task quality, capability, estimated cost, speed, reliability and a small curated-order prior. The weights differ per profile (see [Profile weights](#profile-weights)).
12
+ 4. **Recover.** The full ranked list stays on the decision as `candidates`. The proxy walks it on a timeout or 5xx, so a provider outage costs a retry, not the task.
13
+
14
+ The tables show each tier's **curated primary** and its fallback chain as configured in router-core. Under the portfolio strategy the primary is the head of the candidate pool and carries the curated-order prior; it is the usual winner, not a guarantee — a request that needs vision or a 1M context can legitimately land on a fallback.
15
+
16
+ ---
6
17
 
7
- Use `blockrun/eco` for maximum cost savings.
18
+ ## AUTO (Balanced — Default)
8
19
 
9
- | Tier | Primary Model | Input | Output |
10
- | --------- | ---------------------------- | ----- | ------ |
11
- | SIMPLE | free/gpt-oss-120b | $0.00 | $0.00 |
12
- | MEDIUM | google/gemini-3.1-flash-lite | $0.25 | $1.50 |
13
- | COMPLEX | google/gemini-3.1-flash-lite | $0.25 | $1.50 |
14
- | REASONING | xai/grok-4-1-fast-reasoning | $0.20 | $0.50 |
20
+ Use `blockrun/auto` (or `/model auto`) for the best quality/price balance.
21
+
22
+ | Tier | Primary Model | Input | Output | Fallback chain (in order) |
23
+ | --------- | --------------------------- | ----- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
24
+ | SIMPLE | google/gemini-2.5-flash | $0.30 | $2.50 | gemini-3-flash-preview → deepseek-chat → kimi-k2.5 → gemini-3.1-flash-lite → gemini-2.5-flash-lite → gpt-5.4-nano → grok-4-fast-non-reasoning → step-3.7-flash (free) |
25
+ | MEDIUM | moonshot/kimi-k2.7 | $0.95 | $4.00 | kimi-k2.6 → kimi-k2.5 → gemini-3-flash-preview → deepseek-chat → gemini-2.5-flash → gemini-3.1-flash-lite → gemini-2.5-flash-lite → grok-4-1-fast-non-reasoning → grok-3-mini |
26
+ | COMPLEX | google/gemini-3.1-pro | $2.00 | $12.00 | gemini-3-flash-preview → grok-4-0709 → gemini-2.5-pro → claude-sonnet-5 → claude-sonnet-4.6 → deepseek-chat → gemini-2.5-flash → gpt-5.6-terra → gpt-5.5 → gpt-5.4 |
27
+ | REASONING | xai/grok-4-1-fast-reasoning | $0.20 | $0.50 | grok-4-fast-reasoning → deepseek-reasoner → deepseek-v4-pro → o4-mini → o3 |
15
28
 
16
29
  ---
17
30
 
18
- ## AUTO (Balanced - Default)
31
+ ## ECO (Absolute Cheapest)
32
+
33
+ Use `blockrun/eco` for maximum cost savings. The first stop is the free tier, so simple requests can cost $0.00.
19
34
 
20
- Use `blockrun/auto` for the best quality/price balance.
35
+ | Tier | Primary Model | Input | Output | Fallback chain (in order) |
36
+ | --------- | ---------------------------- | ----- | ------ | --------------------------------------------------------------------------------------------------------------------- |
37
+ | SIMPLE | free/step-3.7-flash | $0.00 | $0.00 | nemotron-nano-9b-v2 (free) → gemini-3.1-flash-lite → gpt-5.4-nano → gemini-2.5-flash-lite → grok-4-fast-non-reasoning |
38
+ | MEDIUM | google/gemini-3.1-flash-lite | $0.25 | $1.50 | gpt-5.4-nano → gemini-2.5-flash-lite → grok-4-fast-non-reasoning → gemini-2.5-flash |
39
+ | COMPLEX | google/gemini-3.1-flash-lite | $0.25 | $1.50 | gemini-2.5-flash-lite → grok-4-0709 → gemini-2.5-flash → deepseek-chat |
40
+ | REASONING | xai/grok-4-1-fast-reasoning | $0.20 | $0.50 | grok-4-fast-reasoning → deepseek-reasoner → deepseek-v4-pro |
21
41
 
22
- | Tier | Primary Model | Input | Output |
23
- | --------- | --------------------------- | ----- | ------ |
24
- | SIMPLE | google/gemini-2.5-flash | $0.30 | $2.50 |
25
- | MEDIUM | moonshot/kimi-k2.6 | $0.95 | $4.00 |
26
- | COMPLEX | google/gemini-3.1-pro | $2.00 | $12.00 |
27
- | REASONING | xai/grok-4-1-fast-reasoning | $0.20 | $0.50 |
42
+ The two free rungs at the head of ECO SIMPLE follow NVIDIA's free hosting, which retires models without notice (deepseek-v4-flash 410'd 2026-08-12, seed-oss-36b 2026-08-03, gpt-oss-120b hung 2026-08-16). Each retirement retargets the free rungs to the current free tier; the paid rungs never move. `src/router/free-model-liveness.test.ts` fails the build if a chain names a free model the picker no longer lists.
28
43
 
29
44
  ---
30
45
 
31
46
  ## PREMIUM (Best Quality)
32
47
 
33
- Use `blockrun/premium` for maximum quality.
48
+ Use `blockrun/premium` for maximum quality. Codex for complex coding, Kimi for simple coding, Sonnet for reasoning/instructions, Fable/Opus for architecture, audits and PM-grade work.
49
+
50
+ | Tier | Primary Model | Input | Output | Fallback chain (in order) |
51
+ | --------- | --------------------------- | ------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
52
+ | SIMPLE | moonshot/kimi-k2.7 | $0.95 | $4.00 | kimi-k2.6 → kimi-k2.5 → gemini-2.5-flash → claude-haiku-4.5 → gemini-2.5-flash-lite → deepseek-chat |
53
+ | MEDIUM | openai/gpt-5.3-codex | $1.75 | $14.00 | kimi-k2.7 → kimi-k2.6 → kimi-k2.5 → gemini-2.5-flash → gemini-2.5-pro → grok-4-0709 → claude-sonnet-5 → claude-sonnet-4.6 |
54
+ | COMPLEX | anthropic/claude-fable-5 | $10.00 | $50.00 | claude-opus-5 → claude-opus-4.8 → claude-opus-4.7 → claude-opus-4.6 → claude-sonnet-5 → claude-sonnet-4.6 → grok-4.5 → grok-4-0709 → kimi-k2.7 → kimi-k2.6 → kimi-k2.5 → gpt-5.6-terra → gpt-5.5 → gpt-5.4 → gpt-5.3-codex → deepseek-chat → step-3.7-flash (free) |
55
+ | REASONING | anthropic/claude-sonnet-4.6 | $3.00 | $15.00 | claude-sonnet-5 → claude-opus-5 → claude-opus-4.8 → claude-opus-4.7 → claude-opus-4.6 → grok-4-1-fast-reasoning → o4-mini → o3 |
56
+
57
+ The premium COMPLEX chain is deliberately de-Gemini'd: Google's "high demand" 503s correlate with Anthropic outages (everyone falls back to Google at the same time), so the chain prefers the in-family Opus hot swaps, then xAI, Moonshot and OpenAI — providers on independent infrastructure.
58
+
59
+ ---
60
+
61
+ ## AGENTIC (Multi-Step Tool Use)
62
+
63
+ Not a profile you pick — router-core switches to these tiers when the turn actually needs its attached tools (`inferToolRequirement`: `tool_choice: "none"` is authoritative, and host tool _descriptions_ alone do not trigger it). Primaries favour models that keep going instead of stopping to ask.
64
+
65
+ | Tier | Primary Model | Input | Output | Fallback chain (in order) |
66
+ | --------- | --------------------------- | ----- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
67
+ | SIMPLE | openai/gpt-4o-mini | $0.15 | $0.60 | kimi-k2.5 → claude-haiku-4.5 → grok-4-1-fast-non-reasoning |
68
+ | MEDIUM | moonshot/kimi-k2.7 | $0.95 | $4.00 | kimi-k2.6 → kimi-k2.5 → grok-4-1-fast-non-reasoning → gpt-4o-mini → claude-haiku-4.5 → deepseek-chat |
69
+ | COMPLEX | anthropic/claude-sonnet-4.6 | $3.00 | $15.00 | claude-sonnet-5 → claude-opus-5 → claude-opus-4.8 → claude-opus-4.7 → claude-opus-4.6 → grok-4-0709 → kimi-k2.7 → kimi-k2.5 → gpt-5.6-terra → gpt-5.5 → gpt-5.4 → deepseek-chat → step-3.7-flash (free) |
70
+ | REASONING | anthropic/claude-sonnet-4.6 | $3.00 | $15.00 | claude-sonnet-5 → claude-opus-5 → claude-opus-4.8 → claude-opus-4.7 → claude-opus-4.6 → grok-4-1-fast-reasoning → deepseek-reasoner |
71
+
72
+ Set `routing.overrides.agenticMode: false` to disable the agentic tier set, or `true` to force it.
73
+
74
+ ---
75
+
76
+ ## FREE (`/model free`)
77
+
78
+ `free` is an alias, not a routed profile: it pins the free-tier default, currently **`free/step-3.7-flash`** — the same model that opens ECO SIMPLE. If that model is excluded (`/exclude add step-flash`) or the budget cap forces a free fallback, the proxy walks the free cascade in this order: step-3.7-flash → nemotron-nano-9b-v2 → mistral-nemotron → nemotron-3-nano-omni-30b-a3b-reasoning (vision) → nemotron-nano-12b-v2-vl (vision). All five are NVIDIA-hosted, $0.00, and need no USDC.
34
79
 
35
- | Tier | Primary Model | Input | Output |
36
- | --------- | -------------------- | ------ | ------ |
37
- | SIMPLE | moonshot/kimi-k2.6 | $0.95 | $4.00 |
38
- | MEDIUM | openai/gpt-5.3-codex | $1.75 | $14.00 |
39
- | COMPLEX | claude-fable-5 | $10.00 | $50.00 |
40
- | REASONING | claude-sonnet-4.6 | $3.00 | $15.00 |
80
+ Pin any of them directly with `/model step-flash`, `/model nemotron-nano`, `/model mistral-nemotron`, `/model nemotron-omni` (vision) or `/model nano-vl` (vision).
41
81
 
42
82
  ---
43
83
 
44
- ## AGENTIC (Multi-Step Tasks)
84
+ ## Profile weights
45
85
 
46
- ClawRouter auto-detects agentic patterns (tool use, multi-step autonomy) and switches to agent-tuned primaries.
86
+ How survivors are ranked, per profile (router-core `DEFAULT_ROUTING_CONFIG.portfolio`):
47
87
 
48
- | Tier | Primary Model | Input | Output |
49
- | --------- | ------------------ | ----- | ------ |
50
- | SIMPLE | openai/gpt-4o-mini | $0.15 | $0.60 |
51
- | MEDIUM | moonshot/kimi-k2.6 | $0.95 | $4.00 |
52
- | COMPLEX | claude-sonnet-4.6 | $3.00 | $15.00 |
53
- | REASONING | claude-sonnet-4.6 | $3.00 | $15.00 |
88
+ | Component | AUTO | ECO | PREMIUM | Role |
89
+ | ------------- | ---: | ---: | ------: | ------------------------------------------------------- |
90
+ | Task quality | 0.47 | 0.36 | 0.58 | Prefer models validated for the detected task shape |
91
+ | Capability | 0.20 | 0.20 | 0.20 | Preserve the request contract after hard filtering |
92
+ | Cost | 0.18 | 0.28 | 0.08 | Reward efficient qualified candidates |
93
+ | Speed | 0.07 | 0.10 | 0.06 | Ordinary interactive latency |
94
+ | Reliability | 0.03 | 0.04 | 0.06 | Prefer stable candidates |
95
+ | Curated order | 0.05 | 0.02 | 0.02 | A small, explainable prior toward the chain order above |
96
+
97
+ High-stakes turns add `+0.08` quality / `+0.05` reliability; latency-sensitive turns add `+0.08` speed. An `affinityFloorGap` (auto 0.10, eco 0.22, premium 0.05) stops a candidate materially below the best task affinity from winning on price alone — which is why ECO can still climb to a paid model for work the free tier would botch.
54
98
 
55
99
  ---
56
100
 
57
101
  ## ECO vs AUTO Savings
58
102
 
59
- Combined input + output rate per 1M tokens:
103
+ Combined input + output rate per 1M tokens, primaries only:
60
104
 
61
105
  | Tier | ECO | AUTO | Savings |
62
106
  | --------- | ----- | ------ | -------- |
@@ -65,21 +109,26 @@ Combined input + output rate per 1M tokens:
65
109
  | COMPLEX | $1.75 | $14.00 | **88%** |
66
110
  | REASONING | $0.70 | $0.70 | 0% |
67
111
 
112
+ The published savings claim (**88%** on `auto`, **98%** on `eco`, against pinning Claude Opus 5) is blended across a stated workload mix and priced on the live catalog — see [`savings-mix.json`](https://github.com/BlockRunAI/blockrun/blob/main/src/brand/savings-mix.json). Per-tier numbers above are illustrative; the blended figure is the one to quote.
113
+
68
114
  ---
69
115
 
70
116
  ## How Tiers Work
71
117
 
72
- ClawRouter automatically classifies your query into one of four tiers:
118
+ - **SIMPLE**: factual lookups, greetings, translations, short responses
119
+ - **MEDIUM**: summaries, explanations, data extraction, moderate code
120
+ - **COMPLEX**: large context, multi-step analysis, substantial code generation
121
+ - **REASONING**: proofs, formal logic, multi-step math, chain-of-thought
122
+
123
+ Two overrides apply on top of the scorer: conversations above 100K tokens are forced to COMPLEX, and structured-output requests (JSON/YAML) are lifted to at least MEDIUM. Ambiguous requests (confidence < 0.7) default to MEDIUM.
73
124
 
74
- - **SIMPLE**: Basic questions, short responses, simple lookups
75
- - **MEDIUM**: Code generation, moderate complexity tasks
76
- - **COMPLEX**: Large context, multi-step reasoning, complex code
77
- - **REASONING**: Logic puzzles, math, chain-of-thought tasks
125
+ ## Rollback and shadow mode
78
126
 
79
- The router picks the cheapest model capable of handling your query's tier.
127
+ - `routing.strategy: "rules"` reverts to the V2 tier selector (primary-first, no portfolio ranking) without a code change.
128
+ - `routing.shadow: { strategy: "rules", sampleRate: 0.1 }` recomputes a comparison decision locally on a sample of requests and reports it on `x-clawrouter-*` debug headers. It never issues a second paid completion and never persists prompt content.
80
129
 
81
- There is also a `blockrun/free` pin that routes exclusively across the free NVIDIA-hosted fleet (gpt-oss-120b default) — no USDC required.
130
+ See [configuration.md](./configuration.md#routing-configuration) for the YAML.
82
131
 
83
132
  ---
84
133
 
85
- _Last updated: v0.12.201_
134
+ _Last updated: v0.12.250 — router-core V3.4 (commit `d7bc10c`)_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/clawrouter",
3
- "version": "0.12.248",
3
+ "version": "0.12.250",
4
4
  "description": "Smart LLM router — save 88% on inference costs. 71 models (5 free), one wallet, x402 micropayments.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -44,6 +44,7 @@
44
44
  "dev": "tsup --watch",
45
45
  "test": "vitest run",
46
46
  "test:watch": "vitest",
47
+ "test:integration": "vitest run --config vitest.integration.config.ts",
47
48
  "typecheck": "tsc --noEmit",
48
49
  "lint": "eslint src/",
49
50
  "format": "prettier --write .",
@@ -86,7 +86,7 @@ ClawRouter does **not** collect or forward third-party provider API keys. You do
86
86
  | `walletKey` | Yes | EVM private key used to sign USDC micropayments via x402. **Auto-generated locally on first run** — no user input required. Never transmitted over the network; only detached payment signatures are sent. |
87
87
  | `solanaKey` | Yes | Solana keypair (BIP-44 `m/44'/501'/0'/0'`). Auto-derived from the same local mnemonic via `@scure/bip32` + `@scure/bip39`. |
88
88
  | `gateway` | No | Gateway URL. Defaults: `https://sol.blockrun.ai/api` (Solana, default chain for new installs) · `https://blockrun.ai/api` (Base, default for pre-existing installs). |
89
- | `routing` | No | Optional override of the default four-tier router. |
89
+ | `routing` | No | Optional override of the router-core config (tier chains, `strategy: "rules"` rollback, `shadow` comparison, scorer keywords). |
90
90
 
91
91
  **How and where keys are stored:**
92
92
 
@@ -124,21 +124,27 @@ openclaw models set openai/gpt-4o
124
124
 
125
125
  ## How Routing Works
126
126
 
127
- ClawRouter classifies each request into one of four tiers:
127
+ Routing is done locally by [`@blockrun/router-core`](https://github.com/BlockRunAI/router-core) (Router Core V3.4, constraint-first), inlined into ClawRouter and pinned by commit. No network call, no second model — about a quarter of a millisecond per request.
128
+
129
+ 1. A 15-dimension weighted scorer classifies each request into one of four tiers, and a task classifier labels the shape of the work (chat, extraction, code_edit, code_agent, tool_agent, reasoning_math, long_context, vision, …).
130
+ 2. Models that cannot satisfy the request — no tool calling, no vision, too small a context window or max-output, incompatible structured output — are removed before anything is scored.
131
+ 3. Survivors are ranked on task quality, capability, estimated cost, speed and reliability; the full ranked list is kept as the fallback chain for timeouts and 5xx.
132
+
133
+ Curated primaries on the default `auto` profile:
128
134
 
129
135
  - **SIMPLE** — factual lookups, greetings, translations → gemini-2.5-flash ($0.30/$2.50)
130
136
  - **MEDIUM** — summaries, explanations, data extraction → kimi-k2.7 ($0.95/$4.00)
131
137
  - **COMPLEX** — code generation, multi-step analysis → gemini-3.1-pro ($2/$12)
132
138
  - **REASONING** — proofs, formal logic, multi-step math → grok-4-1-fast-reasoning ($0.20/$0.50)
133
139
 
134
- Prices are per 1M input/output tokens, on the default `auto` profile. Per-tier
140
+ Turns that actually need their attached tools switch to agent-tuned tiers (gpt-4o-mini → kimi-k2.7 → claude-sonnet-4.6). `eco` opens on the free tier (step-3.7-flash); `premium` climbs to gpt-5.3-codex / claude-fable-5 / claude-sonnet-4.6. Full chains: [docs/routing-profiles.md](../../docs/routing-profiles.md).
141
+
142
+ Prices are per 1M input/output tokens. Per-tier
135
143
  savings percentages are deliberately not quoted here: the published figure is
136
144
  blended across a stated workload mix, and a per-tier number invites comparing
137
145
  it against a baseline nobody wrote down. See
138
146
  [savings-mix.json](https://github.com/BlockRunAI/blockrun/blob/main/src/brand/savings-mix.json).
139
147
 
140
- Rules handle ~~80% of requests in <1ms. Only ambiguous queries hit the LLM classifier (~~$0.00003 per classification).
141
-
142
148
  ## Available Models
143
149
 
144
150
  <!-- br:models.chatVisible -->71<!-- /br:models.chatVisible --> models including: gpt-5.6-terra [balanced, stable default], gpt-5.6-sol [flagship], gpt-5.6-luna [cost-efficient], gpt-5.6-sol/terra/luna-pro [pro reasoning tiers], gpt-5.5, gpt-5.5-pro [max compute], chat-latest [ChatGPT Instant], gpt-5.4, gpt-4o, o3, claude-fable-5, claude-opus-5 [Anthropic flagship, 1M ctx], claude-opus-4.8, claude-opus-4.7, claude-opus-4.5, claude-sonnet-5, claude-sonnet-4.6, gemini-3.1-pro, gemini-3.6-flash, gemini-3.5-flash-lite, gemini-2.5-flash, deepseek-v4-pro, deepseek-chat, grok-4.5, grok-4.3, grok-build-0.1, kimi-k3 [1M ctx flagship], kimi-k2.7, qwen3.7-max [Qwen flagship, 1M ctx], qwen3.7-plus, qwen3.7-flash, hy3 [Tencent], mimo [Xiaomi MiMo-V2.5 Pro, 1M ctx], and 5 free NVIDIA models (nemotron-3-nano-omni-30b-a3b-reasoning [vision], mistral-nemotron, step-3.7-flash, nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl [vision]).
@@ -164,7 +170,7 @@ Realtime prices and historical OHLC across every asset class. The agent should c
164
170
 
165
171
  | Tool | Purpose | Price |
166
172
  | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
167
- | `blockrun_image_generation` | 9 image models — GPT Image 1/2, Nano Banana / 2 / Pro, Seedream 5 Pro, Grok Imagine / Pro, CogView-4 | $0.015–$0.15 / image |
173
+ | `blockrun_image_generation` | 9 image models — GPT Image 1/2, Nano Banana / 2 / Pro, Seedream 5 Pro, Grok Imagine / Pro, CogView-4 | $0.015–$0.15 / image |
168
174
  | `blockrun_image_edit` | Edit / inpaint existing image (openai/gpt-image-1) | $0.02–$0.04 / image |
169
175
  | `blockrun_video_generation` | Grok Imagine + ByteDance Seedance (1.5-pro / 2.0-fast / 2.0) at 720p with synced audio (t2v default), 5–10s, + OpenAI Sora 2 via Azure (`azure/sora-2`, 4/8/12s, t2v + i2v, rejects human faces in reference images). Seedance is token-priced upstream (~20,256 tokens/sec at the 720p+audio default — 2× the prior 480p rate); `image_url` (image-to-video) costs the same as t2v since 2026-06-01. Seedance 2.0 variants accept optional `real_face_asset_id` (`ta_…`) for BytePlus RealFace character-consistency — mutually exclusive with `image_url`. | $0.05/s (Grok); $0.10/s (Sora 2); Seedance ~$0.46–$1.49 per 5s clip |
170
176