@blockrun/clawrouter 0.12.235 → 0.12.237

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
@@ -7,7 +7,7 @@
7
7
  <p>Agents can't sign up for accounts. Agents can't enter credit cards.<br>
8
8
  Agents can only sign transactions.<br><br>
9
9
  <strong>ClawRouter is the only LLM router that lets agents operate independently.</strong><br><br>
10
- <em>8 models free, no crypto required. No signup. No API key. No credit card.</em></p>
10
+ <em><!-- br:models.free -->8<!-- /br:models.free --> models free, no crypto required. No signup. No API key. No credit card.</em></p>
11
11
 
12
12
  <br>
13
13
 
@@ -34,7 +34,7 @@ Agents can only sign transactions.<br><br>
34
34
 
35
35
  </div>
36
36
 
37
- > **ClawRouter** is an open-source smart LLM router that reduces AI API costs by up to 92%. It analyzes each request across 15 dimensions and routes to the cheapest capable model in under 1ms, entirely locally. ClawRouter is the only LLM router built for autonomous AI agents — it uses wallet signatures for authentication (no API keys) and USDC micropayments via the x402 protocol (no credit cards). 55+ models from OpenAI, Anthropic, Google, xAI, DeepSeek, and more. MIT licensed.
37
+ > **ClawRouter** is an open-source smart LLM router that reduces AI API costs by up to <!-- br:savings.autoVsBaselinePct -->87<!-- /br:savings.autoVsBaselinePct -->%. It analyzes each request across <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions and routes to the cheapest capable model in under 1ms, entirely locally. ClawRouter is the only LLM router built for autonomous AI agents — it uses wallet signatures for authentication (no API keys) and USDC micropayments via the x402 protocol (no credit cards). <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models from OpenAI, Anthropic, Google, xAI, DeepSeek, and more. MIT licensed.
38
38
 
39
39
  ---
40
40
 
@@ -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** — 8 NVIDIA models are free forever (incl. 675B Mistral Large 3, 262K-context Qwen3-Next 80B + a vision-capable Nemotron Omni)
49
+ - **Starts at $0** — <!-- br:models.free -->8<!-- /br:models.free --> NVIDIA models are free forever (incl. 262K-context Qwen3-Next 80B, DeepSeek V4 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** — 15-dimension scoring picks the right model automatically
52
+ - **No model selection** — <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions -->-dimension scoring 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
 
@@ -59,16 +59,16 @@ This is the stack that lets agents operate autonomously: **x402 + USDC + local r
59
59
 
60
60
  ## How it compares
61
61
 
62
- | | OpenRouter | LiteLLM | Martian | Portkey | **ClawRouter** |
63
- | ---------------- | ----------------- | ---------------- | ----------------- | ----------------- | ----------------------- |
64
- | **Models** | 200+ | 100+ | Smart routing | Gateway | **55+** |
65
- | **Free tier** | Rate-limited | BYO keys | No | No | **8 models, no signup** |
66
- | **Routing** | Manual selection | Manual selection | Smart (closed) | Observability | **Smart (open source)** |
67
- | **Auth** | Account + API key | Your API keys | Account + API key | Account + API key | **Wallet signature** |
68
- | **Payment** | Credit card | BYO keys | Credit card | $49-499/mo | **USDC per-request** |
69
- | **Runs locally** | No | Yes | No | No | **Yes** |
70
- | **Open source** | No | Yes | No | Partial | **Yes** |
71
- | **Agent-ready** | No | No | No | No | **Yes** |
62
+ | | OpenRouter | LiteLLM | Martian | Portkey | **ClawRouter** |
63
+ | ---------------- | ----------------- | ---------------- | ----------------- | ----------------- | ---------------------------------------------------------------------- |
64
+ | **Models** | 200+ | 100+ | Smart routing | Gateway | **<!-- br:models.chatVisible -->66<!-- /br:models.chatVisible -->** |
65
+ | **Free tier** | Rate-limited | BYO keys | No | No | **<!-- br:models.free -->8<!-- /br:models.free --> models, no signup** |
66
+ | **Routing** | Manual selection | Manual selection | Smart (closed) | Observability | **Smart (open source)** |
67
+ | **Auth** | Account + API key | Your API keys | Account + API key | Account + API key | **Wallet signature** |
68
+ | **Payment** | Credit card | BYO keys | Credit card | $49-499/mo | **USDC per-request** |
69
+ | **Runs locally** | No | Yes | No | No | **Yes** |
70
+ | **Open source** | No | Yes | No | Partial | **Yes** |
71
+ | **Agent-ready** | No | No | No | No | **Yes** |
72
72
 
73
73
  ✓ Open source · ✓ Smart routing · ✓ Runs locally · ✓ Crypto native · ✓ Agent ready
74
74
 
@@ -78,7 +78,7 @@ This is the stack that lets agents operate autonomously: **x402 + USDC + local r
78
78
 
79
79
  ## Quick Start
80
80
 
81
- > **No wallet? 8 models work free out of the box.** Install, run, and pin `free/mistral-large-3-675b` (or any of the 8) — no crypto, no signup, no balance required. Add USDC later when you want paid models.
81
+ > **No wallet? <!-- br:models.free -->8<!-- /br:models.free --> models work free out of the box.** Install, run, and pin `free/mistral-nemotron` (or any of the <!-- br:models.free -->8<!-- /br:models.free -->) — no crypto, no signup, no balance required. Add USDC later when you want paid models.
82
82
 
83
83
  ### Option A — OpenClaw Agent
84
84
 
@@ -107,7 +107,7 @@ openclaw gateway restart
107
107
 
108
108
  > **Using Claude Code?** Check out [BRCC](https://blockrun.ai/brcc.md) — it's purpose-built for Claude Code with the same smart routing and x402 payments.
109
109
  >
110
- > **Using NousResearch Hermes?** See [ClawRouter-Hermes](https://github.com/BlockRunAI/ClawRouter-Hermes) — a Python plugin that wires Hermes into the ClawRouter proxy. Same wallet, same 55+ models, same x402 USDC settlement on Base & Solana.
110
+ > **Using NousResearch Hermes?** See [ClawRouter-Hermes](https://github.com/BlockRunAI/ClawRouter-Hermes) — a Python plugin that wires Hermes into the ClawRouter proxy. Same wallet, same <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models, same x402 USDC settlement on Base & Solana.
111
111
 
112
112
  No OpenClaw required. ClawRouter runs as a local proxy on port 8402.
113
113
 
@@ -118,7 +118,7 @@ npx @blockrun/clawrouter
118
118
  ```
119
119
 
120
120
  **2. Fund your wallet** — optional, skip for free tier
121
- Your wallet address is printed on first run. For paid models, send a few USDC on Base or Solana — $5 covers thousands of requests. To stay at $0, pin any of the 8 free models (e.g. `free/mistral-large-3-675b`) or use `/model free` inside OpenClaw.
121
+ Your wallet address is printed on first run. For paid models, send a few USDC on Base or Solana — $5 covers thousands of requests. To stay at $0, pin any of the <!-- br:models.free -->8<!-- /br:models.free --> free models (e.g. `free/mistral-nemotron`) or use `/model free` inside OpenClaw.
122
122
 
123
123
  **3. Point your client at `http://localhost:8402`**
124
124
 
@@ -188,12 +188,14 @@ 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) | 74-100% | General use |
195
- | `/model eco` | Cheapest possible | 95-100% | Maximum savings |
196
- | `/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) | † 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 -->87<!-- /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 |
197
199
 
198
200
  **Shortcuts:** `/model grok`, `/model br-sonnet`, `/model gpt5`, `/model o3`
199
201
 
@@ -204,17 +206,24 @@ Choose your routing strategy with `/model <profile>`:
204
206
  **100% local routing. <1ms latency. Zero external API calls.**
205
207
 
206
208
  ```
207
- Request → Weighted Scorer (15 dimensions) → Tier → Best Model → Response
209
+ Request → Weighted Scorer (<!-- br:clawrouter.dimensions -->14<!-- /br:clawrouter.dimensions --> dimensions) → Tier → Best Model → Response
208
210
  ```
209
211
 
210
- | Tier | ECO Model | AUTO Model | PREMIUM Model |
211
- | --------- | ------------------------------------ | ------------------------------- | ---------------------------- |
212
- | SIMPLE | free/mistral-large-3-675b (**FREE**) | gemini-2.5-flash ($0.30/$2.50) | kimi-k2.7 ($0.95/$4.00) |
213
- | 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) |
214
- | COMPLEX | gemini-3.1-flash-lite ($0.25/$1.50) | gemini-3.1-pro ($2/$12) | claude-fable-5 ($10/$50) |
215
- | REASONING | deepseek-reasoner ($0.20/$0.40) | deepseek-reasoner ($0.20/$0.40) | claude-sonnet-4.6 ($3/$15) |
212
+ | Tier | ECO Model | AUTO Model | PREMIUM Model |
213
+ | --------- | --------------------------------------- | --------------------------------------- | ---------------------------- |
214
+ | SIMPLE | free/gpt-oss-120b † (**FREE**) | gemini-2.5-flash ($0.30/$2.50) | kimi-k2.7 † ($0.95/$4.00) |
215
+ | 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) |
216
+ | COMPLEX | gemini-3.1-flash-lite ($0.25/$1.50) | gemini-3.1-pro ($2/$12) | claude-fable-5 ($10/$50) |
217
+ | 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) |
218
+
219
+ **<!-- br:savings.autoVsBaselinePct -->87<!-- /br:savings.autoVsBaselinePct -->% cheaper than pinning Claude Opus 5** for the same traffic, on `auto`; **<!-- br:savings.ecoVsBaselinePct -->98<!-- /br:savings.ecoVsBaselinePct -->%** on `eco`.
216
220
 
217
- **Blended average: $2.05/M** vs $25/M for Claude Opus = **92% savings**
221
+ Not an "up to" figure. The baseline, the workload mix and the token ratio are
222
+ published in [`savings-mix.json`](https://github.com/BlockRunAI/blockrun/blob/main/src/brand/savings-mix.json),
223
+ priced against the live catalog, so anyone can recompute it and get the same
224
+ answer. Models withheld from `/v1/models` are excluded from the mix — pricing a
225
+ public claim on a model you cannot look up is not defensible — which makes the
226
+ number conservative.
218
227
 
219
228
  ---
220
229
 
@@ -382,7 +391,7 @@ No Surf account, no API key — settles directly to Surf's Base treasury in USDC
382
391
 
383
392
  ## Models & Pricing
384
393
 
385
- 55+ models across 9 providers, one wallet. **8 models are $0 — paid models start at fractions of a cent.**
394
+ <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models across 9 providers, one wallet. **<!-- br:models.free -->8<!-- /br:models.free --> models are $0 — paid models start at fractions of a cent.**
386
395
 
387
396
  > **💡 "Cost per request"** = estimated cost for a typical chat message (~500 input + 500 output tokens). Paid requests also carry a flat **$0.002/tx settlement fee** (covers on-chain gas; already included in the price the gateway quotes). Free models never pay it.
388
397
 
@@ -637,7 +646,7 @@ npm test
637
646
 
638
647
  **The LLM router built for autonomous agents**
639
648
 
640
- You're here. 55+ models, local smart routing, x402 USDC payments — the only stack that lets agents operate independently.
649
+ You're here. <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models, local smart routing, x402 USDC payments — the only stack that lets agents operate independently.
641
650
 
642
651
  `curl -fsSL https://blockrun.ai/ClawRouter-update | bash`
643
652
 
@@ -648,7 +657,7 @@ You're here. 55+ models, local smart routing, x402 USDC payments — the only st
648
657
 
649
658
  **BlockRun for Claude Code**
650
659
 
651
- Run Claude Code with 50+ models, no rate limits, no Anthropic account, no phone verification. Pay per request with USDC — your wallet is your identity.
660
+ Run Claude Code with <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models, no rate limits, no Anthropic account, no phone verification. Pay per request with USDC — your wallet is your identity.
652
661
 
653
662
  `curl -fsSL https://blockrun.ai/brcc-install | bash`
654
663
 
@@ -661,7 +670,7 @@ Run Claude Code with 50+ models, no rate limits, no Anthropic account, no phone
661
670
 
662
671
  **ClawRouter for NousResearch Hermes**
663
672
 
664
- Python plugin that wraps the ClawRouter proxy for `hermes-agent`. Same 55+ models, same x402 USDC payments on Base & Solana, native Hermes ergonomics.
673
+ Python plugin that wraps the ClawRouter proxy for `hermes-agent`. Same <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models, same x402 USDC payments on Base & Solana, native Hermes ergonomics.
665
674
 
666
675
  `pip install hermes-plugin-clawrouter`
667
676
 
@@ -678,15 +687,15 @@ Python plugin that wraps the ClawRouter proxy for `hermes-agent`. Same 55+ model
678
687
 
679
688
  ## More Resources
680
689
 
681
- | Resource | Description |
682
- | ------------------------------------------------------ | ------------------------ |
683
- | [Documentation](https://blockrun.ai/docs) | Full docs |
684
- | [Model Pricing](https://blockrun.ai/models) | All models & prices |
685
- | [Image Generation & Editing](docs/image-generation.md) | API examples, 8 models |
686
- | [Routing Profiles](docs/routing-profiles.md) | ECO/AUTO/PREMIUM details |
687
- | [Architecture](docs/architecture.md) | Technical deep dive |
688
- | [Configuration](docs/configuration.md) | Environment variables |
689
- | [Troubleshooting](docs/troubleshooting.md) | Common issues |
690
+ | Resource | Description |
691
+ | ------------------------------------------------------ | ----------------------------------------------------------------------- |
692
+ | [Documentation](https://blockrun.ai/docs) | Full docs |
693
+ | [Model Pricing](https://blockrun.ai/models) | All models & prices |
694
+ | [Image Generation & Editing](docs/image-generation.md) | API examples, <!-- br:models.image -->8<!-- /br:models.image --> models |
695
+ | [Routing Profiles](docs/routing-profiles.md) | ECO/AUTO/PREMIUM details |
696
+ | [Architecture](docs/architecture.md) | Technical deep dive |
697
+ | [Configuration](docs/configuration.md) | Environment variables |
698
+ | [Troubleshooting](docs/troubleshooting.md) | Common issues |
690
699
 
691
700
  ### Blog
692
701
 
@@ -705,11 +714,11 @@ Python plugin that wraps the ClawRouter proxy for `hermes-agent`. Same 55+ model
705
714
 
706
715
  ### What is ClawRouter?
707
716
 
708
- ClawRouter is an open-source (MIT licensed) smart LLM router built for autonomous AI agents. It analyzes each request across 15 dimensions and routes to the cheapest capable model in under 1ms, entirely locally — no external API calls needed for routing decisions.
717
+ ClawRouter is an open-source (MIT licensed) smart LLM router built for autonomous AI agents. It analyzes each request across <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions and routes to the cheapest capable model in under 1ms, entirely locally — no external API calls needed for routing decisions.
709
718
 
710
719
  ### How much can ClawRouter save on LLM costs?
711
720
 
712
- ClawRouter's blended average cost is $2.05 per million tokens compared to $25/M for Claude Opus, representing 92% savings. Actual savings depend on your workload — simple queries are routed to free models ($0/request), while complex tasks get premium models.
721
+ On the `auto` profile ClawRouter costs <!-- br:savings.autoVsBaselinePct -->87<!-- /br:savings.autoVsBaselinePct -->% less than pinning Claude Opus 5 for every request, and <!-- br:savings.ecoVsBaselinePct -->98<!-- /br:savings.ecoVsBaselinePct -->% less on `eco`. That is computed from a published workload mix rather than estimated — see [savings-mix.json](https://github.com/BlockRunAI/blockrun/blob/main/src/brand/savings-mix.json) for the baseline and assumptions. Actual savings depend on your workload — simple queries are routed to free models ($0/request), while complex tasks get premium models.
713
722
 
714
723
  ### How does ClawRouter compare to OpenRouter?
715
724
 
package/dist/cli.js CHANGED
@@ -35682,6 +35682,7 @@ var init_models = __esm({
35682
35682
  contextWindow: 1048576,
35683
35683
  maxOutput: 65536,
35684
35684
  reasoning: true,
35685
+ vision: true,
35685
35686
  agentic: true,
35686
35687
  toolCalling: true
35687
35688
  },
@@ -84791,6 +84792,13 @@ function estimateAmount(modelId, bodyLength, maxTokens) {
84791
84792
  const amountMicros = Math.max(1e3, Math.ceil(costUsd * 1.2 * 1e6));
84792
84793
  return amountMicros.toString();
84793
84794
  }
84795
+ function estimateBalancePreflightAmount(modelId, bodyLength, maxTokens) {
84796
+ const preflightMaxTokens = Math.min(
84797
+ maxTokens || BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP,
84798
+ BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP
84799
+ );
84800
+ return estimateAmount(modelId, bodyLength, preflightMaxTokens);
84801
+ }
84794
84802
  function estimatePhoneCost(urlPath) {
84795
84803
  const op = urlPath.replace(/^\/v1\//, "").split("?")[0];
84796
84804
  for (const key2 of Object.keys(PHONE_PRICING).sort((a, b) => b.length - a.length)) {
@@ -87051,9 +87059,13 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
87051
87059
  let isFreeModel = FREE_MODELS.has(modelId ?? "");
87052
87060
  if (modelId && !options.skipBalanceCheck && !isFreeModel) {
87053
87061
  const estimated = estimateAmount(modelId, body.length, maxTokens);
87062
+ const preflightEstimated = estimateBalancePreflightAmount(modelId, body.length, maxTokens);
87054
87063
  if (estimated) {
87055
87064
  estimatedCostMicros = BigInt(estimated);
87056
- const bufferedCostMicros = estimatedCostMicros * BigInt(Math.ceil(BALANCE_CHECK_BUFFER * 100)) / 100n;
87065
+ }
87066
+ if (preflightEstimated) {
87067
+ const preflightEstimatedCostMicros = BigInt(preflightEstimated);
87068
+ const bufferedCostMicros = preflightEstimatedCostMicros * BigInt(Math.ceil(BALANCE_CHECK_BUFFER * 100)) / 100n;
87057
87069
  let sufficiency = null;
87058
87070
  let balanceCheckTimer;
87059
87071
  try {
@@ -87083,6 +87095,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
87083
87095
  );
87084
87096
  modelId = freeFallback;
87085
87097
  isFreeModel = true;
87098
+ estimatedCostMicros = void 0;
87086
87099
  const parsed = JSON.parse(body.toString());
87087
87100
  parsed.model = toUpstreamModelId(freeFallback);
87088
87101
  body = Buffer.from(JSON.stringify(parsed));
@@ -88195,7 +88208,7 @@ data: [DONE]
88195
88208
  });
88196
88209
  }
88197
88210
  }
88198
- var paymentStore, BLOCKRUN_API, BLOCKRUN_SOLANA_API, IMAGE_DIR, AUDIO_DIR, VIDEO_DIR, AUTO_MODEL, ROUTING_PROFILES, FREE_MODELS, FREE_MODEL, MAX_MESSAGES, CONTEXT_LIMIT_KB, HEARTBEAT_INTERVAL_MS, BALANCE_CHECK_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PER_MODEL_TIMEOUT_MS, REASONING_MODEL_TIMEOUT_MS, REASONING_MODEL_IDS, MAX_FALLBACK_ATTEMPTS, HEALTH_CHECK_TIMEOUT_MS, RATE_LIMIT_COOLDOWN_MS, OVERLOAD_COOLDOWN_MS, PORT_RETRY_ATTEMPTS, PORT_RETRY_DELAY_MS, MODEL_BODY_READ_TIMEOUT_MS, ERROR_BODY_READ_TIMEOUT_MS, rateLimitedModels, overloadedModels, perProviderErrors, BALANCE_CHECK_BUFFER, PROVIDER_ERROR_PATTERNS, DEGRADED_RESPONSE_PATTERNS, DEGRADED_LOOP_PATTERNS, VALID_ROLES, ROLE_MAPPINGS, VALID_TOOL_ID_PATTERN, KIMI_BLOCK_RE, KIMI_TOKEN_RE, THINKING_TAG_RE, THINKING_BLOCK_RE, BLOCKRUN_MODEL_BY_ID, IMAGE_PRICING, VIDEO_PRICING, PHONE_PRICING;
88211
+ var paymentStore, BLOCKRUN_API, BLOCKRUN_SOLANA_API, IMAGE_DIR, AUDIO_DIR, VIDEO_DIR, AUTO_MODEL, ROUTING_PROFILES, FREE_MODELS, FREE_MODEL, MAX_MESSAGES, CONTEXT_LIMIT_KB, HEARTBEAT_INTERVAL_MS, BALANCE_CHECK_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PER_MODEL_TIMEOUT_MS, REASONING_MODEL_TIMEOUT_MS, REASONING_MODEL_IDS, MAX_FALLBACK_ATTEMPTS, HEALTH_CHECK_TIMEOUT_MS, RATE_LIMIT_COOLDOWN_MS, OVERLOAD_COOLDOWN_MS, PORT_RETRY_ATTEMPTS, PORT_RETRY_DELAY_MS, MODEL_BODY_READ_TIMEOUT_MS, ERROR_BODY_READ_TIMEOUT_MS, rateLimitedModels, overloadedModels, perProviderErrors, BALANCE_CHECK_BUFFER, BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP, PROVIDER_ERROR_PATTERNS, DEGRADED_RESPONSE_PATTERNS, DEGRADED_LOOP_PATTERNS, VALID_ROLES, ROLE_MAPPINGS, VALID_TOOL_ID_PATTERN, KIMI_BLOCK_RE, KIMI_TOKEN_RE, THINKING_TAG_RE, THINKING_BLOCK_RE, BLOCKRUN_MODEL_BY_ID, IMAGE_PRICING, VIDEO_PRICING, PHONE_PRICING;
88199
88212
  var init_proxy = __esm({
88200
88213
  "src/proxy.ts"() {
88201
88214
  "use strict";
@@ -88287,6 +88300,7 @@ var init_proxy = __esm({
88287
88300
  overloadedModels = /* @__PURE__ */ new Map();
88288
88301
  perProviderErrors = /* @__PURE__ */ new Map();
88289
88302
  BALANCE_CHECK_BUFFER = 1.5;
88303
+ BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP = 4096;
88290
88304
  PROVIDER_ERROR_PATTERNS = [
88291
88305
  /billing/i,
88292
88306
  /insufficient.*balance/i,
package/dist/index.d.ts CHANGED
@@ -512,7 +512,7 @@ type RoutingConfig = {
512
512
  * All routing parameters as a TypeScript constant.
513
513
  * Operators override via openclaw.yaml plugin config.
514
514
  *
515
- * Scoring uses 14 weighted dimensions with sigmoid confidence calibration.
515
+ * Scoring uses 15 weighted dimensions with sigmoid confidence calibration.
516
516
  */
517
517
 
518
518
  declare const DEFAULT_ROUTING_CONFIG: RoutingConfig;
package/dist/index.js CHANGED
@@ -1447,6 +1447,7 @@ var init_models = __esm({
1447
1447
  contextWindow: 1048576,
1448
1448
  maxOutput: 65536,
1449
1449
  reasoning: true,
1450
+ vision: true,
1450
1451
  agentic: true,
1451
1452
  toolCalling: true
1452
1453
  },
@@ -84611,6 +84612,13 @@ function estimateAmount(modelId, bodyLength, maxTokens) {
84611
84612
  const amountMicros = Math.max(1e3, Math.ceil(costUsd * 1.2 * 1e6));
84612
84613
  return amountMicros.toString();
84613
84614
  }
84615
+ function estimateBalancePreflightAmount(modelId, bodyLength, maxTokens) {
84616
+ const preflightMaxTokens = Math.min(
84617
+ maxTokens || BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP,
84618
+ BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP
84619
+ );
84620
+ return estimateAmount(modelId, bodyLength, preflightMaxTokens);
84621
+ }
84614
84622
  function estimatePhoneCost(urlPath) {
84615
84623
  const op = urlPath.replace(/^\/v1\//, "").split("?")[0];
84616
84624
  for (const key2 of Object.keys(PHONE_PRICING).sort((a, b) => b.length - a.length)) {
@@ -86871,9 +86879,13 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
86871
86879
  let isFreeModel = FREE_MODELS.has(modelId ?? "");
86872
86880
  if (modelId && !options.skipBalanceCheck && !isFreeModel) {
86873
86881
  const estimated = estimateAmount(modelId, body.length, maxTokens);
86882
+ const preflightEstimated = estimateBalancePreflightAmount(modelId, body.length, maxTokens);
86874
86883
  if (estimated) {
86875
86884
  estimatedCostMicros = BigInt(estimated);
86876
- const bufferedCostMicros = estimatedCostMicros * BigInt(Math.ceil(BALANCE_CHECK_BUFFER * 100)) / 100n;
86885
+ }
86886
+ if (preflightEstimated) {
86887
+ const preflightEstimatedCostMicros = BigInt(preflightEstimated);
86888
+ const bufferedCostMicros = preflightEstimatedCostMicros * BigInt(Math.ceil(BALANCE_CHECK_BUFFER * 100)) / 100n;
86877
86889
  let sufficiency = null;
86878
86890
  let balanceCheckTimer;
86879
86891
  try {
@@ -86903,6 +86915,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
86903
86915
  );
86904
86916
  modelId = freeFallback;
86905
86917
  isFreeModel = true;
86918
+ estimatedCostMicros = void 0;
86906
86919
  const parsed = JSON.parse(body.toString());
86907
86920
  parsed.model = toUpstreamModelId(freeFallback);
86908
86921
  body = Buffer.from(JSON.stringify(parsed));
@@ -88015,7 +88028,7 @@ data: [DONE]
88015
88028
  });
88016
88029
  }
88017
88030
  }
88018
- var paymentStore, BLOCKRUN_API, BLOCKRUN_SOLANA_API, IMAGE_DIR, AUDIO_DIR, VIDEO_DIR, AUTO_MODEL, ROUTING_PROFILES, FREE_MODELS, FREE_MODEL, MAX_MESSAGES, CONTEXT_LIMIT_KB, HEARTBEAT_INTERVAL_MS, BALANCE_CHECK_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PER_MODEL_TIMEOUT_MS, REASONING_MODEL_TIMEOUT_MS, REASONING_MODEL_IDS, MAX_FALLBACK_ATTEMPTS, HEALTH_CHECK_TIMEOUT_MS, RATE_LIMIT_COOLDOWN_MS, OVERLOAD_COOLDOWN_MS, PORT_RETRY_ATTEMPTS, PORT_RETRY_DELAY_MS, MODEL_BODY_READ_TIMEOUT_MS, ERROR_BODY_READ_TIMEOUT_MS, rateLimitedModels, overloadedModels, perProviderErrors, BALANCE_CHECK_BUFFER, PROVIDER_ERROR_PATTERNS, DEGRADED_RESPONSE_PATTERNS, DEGRADED_LOOP_PATTERNS, VALID_ROLES, ROLE_MAPPINGS, VALID_TOOL_ID_PATTERN, KIMI_BLOCK_RE, KIMI_TOKEN_RE, THINKING_TAG_RE, THINKING_BLOCK_RE, BLOCKRUN_MODEL_BY_ID, IMAGE_PRICING, VIDEO_PRICING, PHONE_PRICING;
88031
+ var paymentStore, BLOCKRUN_API, BLOCKRUN_SOLANA_API, IMAGE_DIR, AUDIO_DIR, VIDEO_DIR, AUTO_MODEL, ROUTING_PROFILES, FREE_MODELS, FREE_MODEL, MAX_MESSAGES, CONTEXT_LIMIT_KB, HEARTBEAT_INTERVAL_MS, BALANCE_CHECK_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PER_MODEL_TIMEOUT_MS, REASONING_MODEL_TIMEOUT_MS, REASONING_MODEL_IDS, MAX_FALLBACK_ATTEMPTS, HEALTH_CHECK_TIMEOUT_MS, RATE_LIMIT_COOLDOWN_MS, OVERLOAD_COOLDOWN_MS, PORT_RETRY_ATTEMPTS, PORT_RETRY_DELAY_MS, MODEL_BODY_READ_TIMEOUT_MS, ERROR_BODY_READ_TIMEOUT_MS, rateLimitedModels, overloadedModels, perProviderErrors, BALANCE_CHECK_BUFFER, BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP, PROVIDER_ERROR_PATTERNS, DEGRADED_RESPONSE_PATTERNS, DEGRADED_LOOP_PATTERNS, VALID_ROLES, ROLE_MAPPINGS, VALID_TOOL_ID_PATTERN, KIMI_BLOCK_RE, KIMI_TOKEN_RE, THINKING_TAG_RE, THINKING_BLOCK_RE, BLOCKRUN_MODEL_BY_ID, IMAGE_PRICING, VIDEO_PRICING, PHONE_PRICING;
88019
88032
  var init_proxy = __esm({
88020
88033
  "src/proxy.ts"() {
88021
88034
  "use strict";
@@ -88107,6 +88120,7 @@ var init_proxy = __esm({
88107
88120
  overloadedModels = /* @__PURE__ */ new Map();
88108
88121
  perProviderErrors = /* @__PURE__ */ new Map();
88109
88122
  BALANCE_CHECK_BUFFER = 1.5;
88123
+ BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP = 4096;
88110
88124
  PROVIDER_ERROR_PATTERNS = [
88111
88125
  /billing/i,
88112
88126
  /insufficient.*balance/i,
@@ -1,5 +1,11 @@
1
1
  # 9 Free AI Models, Zero Cost: How BlockRun Gives Developers Top-Tier LLMs for Nothing
2
2
 
3
+ > **The count in this title is a snapshot.** It was 9 when this was written; the
4
+ > published free tier is now 8 — models are withheld from `/v1/models` when a
5
+ > provider's terms change, most recently over NVIDIA's prompt-retention policy.
6
+ > The URL keeps its original slug so existing links do not break. Current figures:
7
+ > [blockrun.ai/brand/numbers.json](https://blockrun.ai/brand/numbers.json).
8
+
3
9
  ## The Cost Problem Nobody Talks About
4
10
 
5
11
  It's 2026. Large language models are table stakes for developers. But here's the uncomfortable truth — **the models you can afford aren't good enough, and the good ones aren't affordable.**
@@ -80,7 +86,7 @@ Assume 100 requests per day, distributed roughly as:
80
86
  | ClawRouter ECO mode | ~$1–3 |
81
87
  | Manual free model selection | **$0** |
82
88
 
83
- **ECO mode saves 92%+ compared to Claude Opus alone.**
89
+ **ECO mode is <!-- br:savings.ecoVsBaselinePct -->98<!-- /br:savings.ecoVsBaselinePct -->% cheaper than pinning Claude Opus 5 for every request.**
84
90
 
85
91
  ---
86
92
 
@@ -50,7 +50,7 @@ This is where you're paying for real value:
50
50
 
51
51
  ## The Solution: ClawRouter
52
52
 
53
- [ClawRouter](https://github.com/BlockRunAI/ClawRouter) is an open-source local proxy that sits between your app and 41+ AI models. It saves you money in three ways: **smart routing**, **token optimization**, and **response caching**.
53
+ [ClawRouter](https://github.com/BlockRunAI/ClawRouter) is an open-source local proxy that sits between your app and <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> AI models. It saves you money in three ways: **smart routing**, **token optimization**, and **response caching**.
54
54
 
55
55
  ```
56
56
  ┌─────────────┐ ┌──────────────────────────────┐ ┌──────────────────┐
@@ -31,7 +31,7 @@ This is exactly the problem [ClawRouter](https://github.com/BlockRunAI/ClawRoute
31
31
 
32
32
  ## ClawRouter: Smart Routing for Agents
33
33
 
34
- ClawRouter is an open-source local proxy that sits between your agent and 55+ LLM models across 9 providers. It analyzes every request across 15 dimensions and routes it to the cheapest model that can handle it — in under 1ms, entirely locally.
34
+ ClawRouter is an open-source local proxy that sits between your agent and <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> LLM models across 9 providers. It analyzes every request across 15 dimensions and routes it to the cheapest model that can handle it — in under 1ms, entirely locally.
35
35
 
36
36
  ```
37
37
  Your Agent → ClawRouter (localhost:8402) → Best model for the job
@@ -56,7 +56,7 @@ From 20,000+ production requests:
56
56
  | Free models (trivial tasks) | 12.8% | $0.00 |
57
57
  | Others | 13.8% | varies |
58
58
 
59
- **Result: 81% savings vs. Sonnet-for-everything, 89% vs. Opus-for-everything.**
59
+ **Result: <!-- br:savings.autoVsBaselinePct -->87<!-- /br:savings.autoVsBaselinePct -->% cheaper than pinning Claude Opus 5 for every request** — the published figure, priced on a stated workload mix rather than estimated.
60
60
 
61
61
  A typical user running 10K mixed requests/month:
62
62
 
@@ -74,7 +74,7 @@ Then point your agent at `http://localhost:8402/v1/` with any OpenAI-compatible
74
74
 
75
75
  - **No API keys to manage** — wallet-based cryptographic auth
76
76
  - **No subscriptions** — pay per request in USDC (Base or Solana)
77
- - **No vendor lock-in** — 55+ models, switch anytime
77
+ - **No vendor lock-in** — <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models, switch anytime
78
78
  - **You control your wallet** — non-custodial, funds never held by a third party
79
79
  - **Budget caps** — set a max spend per session, ClawRouter gracefully downgrades when budget runs low
80
80
  - **Token compression** — 7-layer pipeline reduces token costs by 7–40% before they hit any provider
@@ -135,7 +135,7 @@ Less context repeated = fewer tokens = lower cost. Agents that need to recall ea
135
135
 
136
136
  ### 7. x402 Micropayments — Wallet-Based Budget Control
137
137
 
138
- <p align="center"><img src="assets/blockrun-clawrouter-x402-usdc-micropayment-wallet-budget-control.png" alt="Budget limits enforced by physical construction — wallet loaded via Base/Solana, pay per call across 41+ models, balance hits zero and the valve shuts cleanly" width="720"></p>
138
+ <p align="center"><img src="assets/blockrun-clawrouter-x402-usdc-micropayment-wallet-budget-control.png" alt="Budget limits enforced by physical construction — wallet loaded via Base/Solana, pay per call across <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models, balance hits zero and the valve shuts cleanly" width="720"></p>
139
139
 
140
140
  ClawRouter pays for inference via [x402](https://x402.org/) USDC micropayments (Base or Solana). You load a wallet. Each inference call costs exactly what it costs. When the wallet runs low, requests stop cleanly.
141
141
 
@@ -144,7 +144,7 @@ There is no monthly invoice. There is no 3am email. There is a wallet balance, a
144
144
  **`maxCostPerRun`** — a per-session cost ceiling that stops or downgrades requests once a session exceeds a configured threshold (e.g., `$0.50`). This closes the remaining gap ([#3181](https://github.com/openclaw/openclaw/issues/3181)) where a wallet with sufficient funds can still accumulate within a single run. Two modes: `graceful` (downgrade to cheaper models) and `strict` (hard 429 once the cap is hit).
145
145
 
146
146
  ```
147
- 41+ models. One wallet. Pay per call.
147
+ <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models. One wallet. Pay per call.
148
148
  ```
149
149
 
150
150
  ---
@@ -222,7 +222,7 @@ OpenRouter doesn't always pass through provider-specific features correctly. Ima
222
222
 
223
223
  **Direct provider routing.** ClawRouter routes through BlockRun's API directly to providers — not through a second aggregator. One hop, not two. Provider-specific features work because there's no middleman translating them.
224
224
 
225
- ![Guaranteed Feature Parity & Direct Connectivity — Three-panel diagram: Vision (image_url auto-detected → vision-capable models only), Tool Calling (toolCalling flag → agentic models only), Catalog (curated 55+ models with automatic legacy-to-modern redirects). Direct provider routing means no dropped payloads.](./assets/clawrouter-feature-parity-direct-connectivity.png)
225
+ ![Guaranteed Feature Parity & Direct Connectivity — Three-panel diagram: Vision (image_url auto-detected → vision-capable models only), Tool Calling (toolCalling flag → agentic models only), Catalog (curated <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models with automatic legacy-to-modern redirects). Direct provider routing means no dropped payloads.](./assets/clawrouter-feature-parity-direct-connectivity.png)
226
226
 
227
227
  ---
228
228
 
@@ -240,7 +240,7 @@ When new models launch, OpenRouter's catalog lags. Users configure a model that
240
240
 
241
241
  ### How ClawRouter Solves This
242
242
 
243
- ClawRouter maintains a curated catalog of 55+ models across 9 providers (including 9 free models), updated with each release. Delisted models have automatic redirect aliases:
243
+ ClawRouter maintains a curated catalog of <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models across 9 providers (including 9 free models), updated with each release. Delisted models have automatic redirect aliases:
244
244
 
245
245
  ```typescript
246
246
  // Delisted models redirect automatically
@@ -256,22 +256,22 @@ No silent drops. No stale catalog. Models are benchmarked for speed, quality, an
256
256
 
257
257
  ## The Full Comparison
258
258
 
259
- | | OpenRouter | ClawRouter |
260
- | ------------------- | -------------------------------- | ---------------------------------------------- |
261
- | **Authentication** | API key (leak risk) | Wallet signature (no keys) |
262
- | **Payment** | Prepaid balance (custodial) | Per-request USDC (non-custodial) |
263
- | **Routing** | Server-side black box | Local 14-dim classifier, <1ms |
264
- | **Fallback** | Often broken (20+ issues) | 8-deep chains, per-model isolation |
265
- | **Model IDs** | Nested prefixes, mangling bugs | Clean aliases, single format |
266
- | **Cost visibility** | None per-request | Headers + JSONL logs + `/stats` |
267
- | **Empty wallet** | Request fails | Auto-fallback to free tier |
268
- | **Rate limits** | Per-key, shared | Per-wallet, independent |
269
- | **Vision support** | Images sometimes dropped | Auto-detected, vision-only fallback |
270
- | **Tool calling** | Silent failures with some models | Flag-based filtering, guaranteed support |
271
- | **Model catalog** | Laggy, silent drops | Curated 55+ models, redirect aliases |
272
- | **Budget control** | Monthly invoice | Per-session cap (`maxCostPerRun`) |
273
- | **Setup** | Create account, paste key | Agent generates wallet, auto-configured |
274
- | **Average cost** | $25/M tokens (Opus direct) | $2.05/M tokens (auto-routed) = **92% savings** |
259
+ | | OpenRouter | ClawRouter |
260
+ | ------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------- |
261
+ | **Authentication** | API key (leak risk) | Wallet signature (no keys) |
262
+ | **Payment** | Prepaid balance (custodial) | Per-request USDC (non-custodial) |
263
+ | **Routing** | Server-side black box | Local 14-dim classifier, <1ms |
264
+ | **Fallback** | Often broken (20+ issues) | 8-deep chains, per-model isolation |
265
+ | **Model IDs** | Nested prefixes, mangling bugs | Clean aliases, single format |
266
+ | **Cost visibility** | None per-request | Headers + JSONL logs + `/stats` |
267
+ | **Empty wallet** | Request fails | Auto-fallback to free tier |
268
+ | **Rate limits** | Per-key, shared | Per-wallet, independent |
269
+ | **Vision support** | Images sometimes dropped | Auto-detected, vision-only fallback |
270
+ | **Tool calling** | Silent failures with some models | Flag-based filtering, guaranteed support |
271
+ | **Model catalog** | Laggy, silent drops | Curated <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models, redirect aliases |
272
+ | **Budget control** | Monthly invoice | Per-session cap (`maxCostPerRun`) |
273
+ | **Setup** | Create account, paste key | Agent generates wallet, auto-configured |
274
+ | **Average cost** | $25/M tokens (Opus direct) | auto-routed = **<!-- br:savings.autoVsBaselinePct -->87<!-- /br:savings.autoVsBaselinePct -->% savings** |
275
275
 
276
276
  ![The Engineering Matrix — Side-by-side feature comparison: OpenRouter vs ClawRouter across Routing, Authentication, Payment, Fallback, Model IDs, Empty Wallet, Vision/Tools, and Average Cost. ClawRouter wins on every dimension.](./assets/clawrouter-engineering-matrix-comparison.png)
277
277
 
@@ -2,6 +2,11 @@
2
2
 
3
3
  _March 16, 2026 | BlockRun Engineering_
4
4
 
5
+ > **Numbers in this post are a snapshot from the date above.** They record what was
6
+ > measured then and are deliberately not updated — rewriting them would misrepresent
7
+ > the benchmark. For current figures see
8
+ > [blockrun.ai/brand/numbers.json](https://blockrun.ai/brand/numbers.json).
9
+
5
10
  Last week we ran every model on BlockRun through a real-world latency benchmark — 39 models, same prompts, same payment pipeline, same hardware. No cherry-picked results. No synthetic lab conditions. Just cold, hard numbers from production infrastructure.
6
11
 
7
12
  The results changed how we route requests.
@@ -2,6 +2,11 @@
2
2
 
3
3
  _March 20, 2026 | BlockRun Engineering_
4
4
 
5
+ > **Numbers in this post are a snapshot from the date above.** They record what was
6
+ > measured then and are deliberately not updated — rewriting them would misrepresent
7
+ > the benchmark. For current figures see
8
+ > [blockrun.ai/brand/numbers.json](https://blockrun.ai/brand/numbers.json).
9
+
5
10
  When you route AI requests across 55+ models from 8 providers, you can't just pick the cheapest one. You can't just pick the fastest one either. We learned this the hard way.
6
11
 
7
12
  This is the technical story of how we benchmarked every model on our platform, discovered that speed and intelligence are poorly correlated, and built a production routing system that classifies requests in under 1ms using 14 weighted dimensions with sigmoid confidence calibration.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blockrun/clawrouter",
3
- "version": "0.12.235",
4
- "description": "Smart LLM router — save 85% on inference costs. 55+ models (8 free), one wallet, x402 micropayments.",
3
+ "version": "0.12.237",
4
+ "description": "Smart LLM router — save 87% on inference costs. 66 models (8 free), one wallet, x402 micropayments.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -0,0 +1,270 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sync marketing numbers from BlockRun's canonical brand artifact.
4
+ *
5
+ * This file is copied byte-for-byte into every public repo as
6
+ * scripts/sync-brand-numbers.mjs. It is a copy rather than an npm package on
7
+ * purpose: a package would mean 37 dependency bumps, and several consuming
8
+ * repos have no package.json at all. Zero dependencies, plain Node.
9
+ *
10
+ * node scripts/sync-brand-numbers.mjs rewrite markers in place
11
+ * node scripts/sync-brand-numbers.mjs --check exit 1 on drift, write nothing
12
+ * node scripts/sync-brand-numbers.mjs --refresh re-fetch the artifact first
13
+ *
14
+ * --check NEVER touches the network. PR CI must be deterministic and offline:
15
+ * if it fetched, a deploy in progress would fail every repo in the org at once.
16
+ * Freshness is the fan-out job's problem, not the pull request's.
17
+ *
18
+ * Markers look like: <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible -->
19
+ * and wrap the WHOLE token, so a badge URL, its alt text and the prose number
20
+ * can all regenerate from one key.
21
+ */
22
+ import { existsSync, lstatSync, readFileSync, writeFileSync, readdirSync } from "node:fs";
23
+ import { join, relative, extname } from "node:path";
24
+
25
+ const ROOT = process.cwd();
26
+ const SNAPSHOT = join(ROOT, "brand-numbers.json");
27
+ // ORIGIN is tried first because it IS the truth — the mirror can only ever be
28
+ // as fresh as the last time someone refreshed it. The mirror exists so a repo
29
+ // can still sync while blockrun.ai is down, not to front the origin.
30
+ //
31
+ // The mirror is awesome-blockrun's own brand-numbers.json: that repo consumes
32
+ // the artifact like every other, and its snapshot doubles as the org's copy.
33
+ // One file, one role per repo, nothing to keep in step by hand.
34
+ const ORIGIN = "https://blockrun.ai/brand/numbers.json";
35
+ const MIRROR =
36
+ "https://raw.githubusercontent.com/BlockRunAI/awesome-blockrun/main/brand-numbers.json";
37
+
38
+ const argv = new Set(process.argv.slice(2));
39
+ const check = argv.has("--check");
40
+ const refresh = argv.has("--refresh");
41
+
42
+ const SKIP_DIRS = new Set([
43
+ "node_modules", ".git", "dist", "build", "out", ".next", "coverage",
44
+ "vendor", "target", "__pycache__", ".venv", "venv",
45
+ ]);
46
+ // .txt is here for llms.txt, which is a first-class marketing surface: it is
47
+ // what agents read to find out what BlockRun serves. Scanning other .txt files
48
+ // costs a read and changes nothing — only files with markers are ever written.
49
+ const TEXT_EXT = new Set([".md", ".mdx", ".txt"]);
50
+
51
+ /* ── 1. numbers ──────────────────────────────────────────────────────────── */
52
+
53
+ async function loadNumbers() {
54
+ if (!refresh) {
55
+ try {
56
+ return JSON.parse(readFileSync(SNAPSHOT, "utf8"));
57
+ } catch {
58
+ fail(
59
+ `no brand-numbers.json in ${ROOT}\n` +
60
+ ` run with --refresh once to seed it from ${ORIGIN}`,
61
+ );
62
+ }
63
+ }
64
+ for (const url of [ORIGIN, MIRROR]) {
65
+ try {
66
+ const res = await fetch(url, { signal: AbortSignal.timeout(10_000) });
67
+ if (!res.ok) continue;
68
+ const json = await res.json();
69
+ writeFileSync(SNAPSHOT, `${JSON.stringify(json, null, 2)}\n`);
70
+ return json;
71
+ } catch {
72
+ /* try the next source */
73
+ }
74
+ }
75
+ fail(`could not refresh from ${MIRROR} or ${ORIGIN}`);
76
+ }
77
+
78
+ /** Flatten nested numbers into dotted keys, ignoring $comment / rationale prose. */
79
+ function flatten(obj, prefix = "") {
80
+ return Object.entries(obj).flatMap(([k, v]) => {
81
+ if (k.startsWith("$")) return [];
82
+ const key = `${prefix}${k}`;
83
+ if (v && typeof v === "object" && !Array.isArray(v)) return flatten(v, `${key}.`);
84
+ if (v === null) return [];
85
+ return [[key, v]];
86
+ });
87
+ }
88
+
89
+ /* ── 2. renderers ────────────────────────────────────────────────────────── */
90
+
91
+ /**
92
+ * How a key becomes text. Default is the bare value.
93
+ *
94
+ * A marker may carry an `@modifier` — `<!-- br:mcp.tools@badge -->` — which
95
+ * selects a renderer without changing which number is looked up. The modifier
96
+ * is what makes a key reusable: the same mcp.tools appears as a shields badge
97
+ * at the top of a README and as a bare "19 tools" in a table two screens down,
98
+ * and one marker still keeps the badge URL, its alt text and the label in step.
99
+ *
100
+ * Renderers are registered under the FULL marker name so a badge's label is
101
+ * written out rather than guessed from the key.
102
+ */
103
+ const badge = (label) => (n) =>
104
+ `<img src="https://img.shields.io/badge/${label}-${n}-5B9BF6?style=flat-square&labelColor=0B0A0F" alt="${n} ${label}">`;
105
+
106
+ const RENDER = {
107
+ "mcp.tools@badge": badge("tools"),
108
+ "models.totalVisible@badge": badge("models"),
109
+ "models.chatVisible@badge": badge("models"),
110
+ };
111
+ const render = (marker, value) => (RENDER[marker] ?? String)(value);
112
+
113
+ /** `mcp.tools@badge` looks up `mcp.tools`. Unmodified markers are unaffected. */
114
+ const keyOf = (marker) => marker.split("@")[0];
115
+
116
+ /* ── 3. marker rewriting ─────────────────────────────────────────────────── */
117
+
118
+ const esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
119
+ const OPEN_ANY = /<!--\s*br:([A-Za-z0-9_.@]+)\s*-->/g;
120
+ const CLOSE_ANY = /<!--\s*\/br:([A-Za-z0-9_.@]+)\s*-->/g;
121
+
122
+ /** Byte ranges of fenced code blocks — markers inside them are documentation. */
123
+ function fencedRanges(text) {
124
+ const ranges = [];
125
+ const fence = /^(\s*)(`{3,}|~{3,})[^\n]*$/gm;
126
+ let open = null;
127
+ for (let m; (m = fence.exec(text)); ) {
128
+ if (open === null) open = m.index;
129
+ else {
130
+ ranges.push([open, m.index + m[0].length]);
131
+ open = null;
132
+ }
133
+ }
134
+ return ranges;
135
+ }
136
+
137
+ function syncFile(file, numbers, problems) {
138
+ const before = readFileSync(file, "utf8");
139
+ const rel = relative(ROOT, file);
140
+ const fenced = fencedRanges(before);
141
+ const inFence = (i) => fenced.some(([a, b]) => i >= a && i < b);
142
+ const known = new Map(numbers);
143
+ const used = new Set();
144
+
145
+ // Markers actually present, so a file is only ever rewritten for what it uses
146
+ // and an @modifier is carried through to the renderer verbatim.
147
+ const markers = new Set();
148
+ // A marker naming a key that does not exist is an error, never a silent
149
+ // no-op: a typo'd marker would otherwise sit there looking synced forever.
150
+ for (const [re, shown] of [
151
+ [OPEN_ANY, (n) => `<!-- br:${n} -->`],
152
+ [CLOSE_ANY, (n) => `<!-- /br:${n} -->`],
153
+ ]) {
154
+ for (const m of before.matchAll(re)) {
155
+ if (inFence(m.index)) continue;
156
+ markers.add(m[1]);
157
+ if (!known.has(keyOf(m[1]))) problems.push(`${rel}: unknown key ${shown(m[1])}`);
158
+ }
159
+ }
160
+
161
+ let after = before;
162
+ for (const marker of markers) {
163
+ const key = keyOf(marker);
164
+ if (!known.has(key)) continue;
165
+ const value = known.get(key);
166
+ const pair = new RegExp(
167
+ `(<!--\\s*br:${esc(marker)}\\s*-->)([\\s\\S]*?)(<!--\\s*/br:${esc(marker)}\\s*-->)`,
168
+ "g",
169
+ );
170
+ after = after.replace(pair, (whole, open, inner, close, offset) => {
171
+ if (inFence(offset)) return whole;
172
+ // Nesting means the closing tag of an inner marker would be consumed by
173
+ // the outer one. Refuse rather than produce mangled output.
174
+ if (/<!--\s*\/?br:/.test(inner)) {
175
+ problems.push(`${rel}: nested marker inside br:${marker}`);
176
+ return whole;
177
+ }
178
+ used.add(marker);
179
+ return open + render(marker, value) + close;
180
+ });
181
+
182
+ // An opening tag with no partner silently swallows the rest of the file on
183
+ // a naive regex, so catch it explicitly.
184
+ const opens = [...before.matchAll(new RegExp(`<!--\\s*br:${esc(marker)}\\s*-->`, "g"))]
185
+ .filter((m) => !inFence(m.index)).length;
186
+ const closes = [...before.matchAll(new RegExp(`<!--\\s*/br:${esc(marker)}\\s*-->`, "g"))]
187
+ .filter((m) => !inFence(m.index)).length;
188
+ if (opens !== closes) problems.push(`${rel}: unbalanced marker br:${marker} (${opens} open, ${closes} close)`);
189
+ }
190
+
191
+ return { before, after, changed: before !== after, used };
192
+ }
193
+
194
+ /* ── 4. walk ─────────────────────────────────────────────────────────────── */
195
+
196
+ function* walk(dir) {
197
+ for (const name of readdirSync(dir)) {
198
+ if (SKIP_DIRS.has(name)) continue;
199
+ const p = join(dir, name);
200
+ // lstat, not stat: a symlinked directory is reached by its real path or not
201
+ // at all. blockrun's docs/ -> awesome-blockrun/docs is exactly the case that
202
+ // matters — following it would edit a submodule's files behind the skip
203
+ // below, and a link pointing at an ancestor would recurse forever.
204
+ const s = lstatSync(p);
205
+ if (s.isSymbolicLink()) continue;
206
+ if (s.isDirectory()) {
207
+ // A nested repo is a submodule or vendored checkout: it carries its own
208
+ // brand-numbers.json and syncs itself. Rewriting its markers from THIS
209
+ // repo's snapshot would dirty a submodule nobody asked us to touch, and
210
+ // would report drift that belongs to another repo's CI.
211
+ if (existsSync(join(p, ".git"))) continue;
212
+ yield* walk(p);
213
+ } else if (TEXT_EXT.has(extname(name))) yield p;
214
+ }
215
+ }
216
+
217
+ function fail(msg) {
218
+ console.error(`brand-numbers: ${msg}`);
219
+ process.exit(1);
220
+ }
221
+
222
+ /* ── 5. run ──────────────────────────────────────────────────────────────── */
223
+
224
+ const raw = await loadNumbers();
225
+ const numbers = flatten(raw);
226
+ const problems = [];
227
+ const drifted = [];
228
+ const everUsed = new Set();
229
+
230
+ for (const file of walk(ROOT)) {
231
+ const { before, after, changed, used } = syncFile(file, numbers, problems);
232
+ used.forEach((k) => everUsed.add(k));
233
+ if (!changed) continue;
234
+ drifted.push({ file: relative(ROOT, file), before, after });
235
+ if (!check) writeFileSync(file, after);
236
+ }
237
+
238
+ if (problems.length) {
239
+ for (const p of problems) console.error(` ${p}`);
240
+ fail(`${problems.length} marker problem(s)`);
241
+ }
242
+
243
+ if (check) {
244
+ if (drifted.length === 0) {
245
+ console.log(`brand-numbers: up to date (${everUsed.size} keys in use)`);
246
+ process.exit(0);
247
+ }
248
+ console.error("brand-numbers: these files disagree with brand-numbers.json\n");
249
+ for (const { file, before, after } of drifted) {
250
+ const b = before.split("\n");
251
+ const a = after.split("\n");
252
+ for (let i = 0; i < Math.max(b.length, a.length); i++) {
253
+ if (b[i] !== a[i]) {
254
+ console.error(` ${file}:${i + 1}`);
255
+ console.error(` - ${(b[i] ?? "").trim()}`);
256
+ console.error(` + ${(a[i] ?? "").trim()}`);
257
+ }
258
+ }
259
+ }
260
+ console.error(
261
+ "\n fix with: node scripts/sync-brand-numbers.mjs && git commit -am 'chore: sync brand numbers'",
262
+ );
263
+ process.exit(1);
264
+ }
265
+
266
+ console.log(
267
+ drifted.length
268
+ ? `brand-numbers: updated ${drifted.length} file(s)`
269
+ : `brand-numbers: already up to date (${everUsed.size} keys in use)`,
270
+ );
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: clawrouter
3
- description: Hosted-gateway LLM router — save 67% on inference costs. A local proxy that forwards each request to the blockrun.ai gateway, which routes to the cheapest capable model across 55+ models from OpenAI, Anthropic, Google, DeepSeek, xAI, NVIDIA, and more. 8 free NVIDIA models included. Also exposes realtime market data (global stocks, crypto, FX, commodities), Twitter/X intelligence, prediction-market data across Polymarket, Kalshi, Limitless, Opinion, Predict.Fun, dFlow + UMA oracle resolution + wallet identity & clustering, phone-number intelligence (carrier + SIM-swap fraud detection) plus AI-powered outbound voice calls (Twilio + Bland.ai), AND the Surf unified crypto data API (84 endpoints — CEX/DEX, on-chain SQL over 80+ ClickHouse tables, 100M+ labeled wallets, prediction markets, social/CT mindshare, news, VC fund intel) as built-in agent tools. Not a local-inference tool — prompts are sent to the blockrun.ai gateway.
3
+ description: Hosted-gateway LLM router — save 87% on inference costs. A local proxy that forwards each request to the blockrun.ai gateway, which routes to the cheapest capable model across 66 models from OpenAI, Anthropic, Google, DeepSeek, xAI, NVIDIA, and more. 8 free NVIDIA models included. Also exposes realtime market data (global stocks, crypto, FX, commodities), Twitter/X intelligence, prediction-market data across Polymarket, Kalshi, Limitless, Opinion, Predict.Fun, dFlow + UMA oracle resolution + wallet identity & clustering, phone-number intelligence (carrier + SIM-swap fraud detection) plus AI-powered outbound voice calls (Twilio + Bland.ai), AND the Surf unified crypto data API (84 endpoints — CEX/DEX, on-chain SQL over 80+ ClickHouse tables, 100M+ labeled wallets, prediction markets, social/CT mindshare, news, VC fund intel) as built-in agent tools. Not a local-inference tool — prompts are sent to the blockrun.ai gateway.
4
4
  triggers:
5
5
  - "clawrouter"
6
6
  - "claw router"
@@ -53,7 +53,7 @@ metadata:
53
53
 
54
54
  # ClawRouter
55
55
 
56
- Hosted-gateway LLM router that saves 67% on inference costs by forwarding each request to the blockrun.ai gateway, which picks the cheapest model capable of handling it across 55+ models from 9 providers (8 free NVIDIA models). All billing flows through one USDC wallet; you do not hold provider API keys.
56
+ Hosted-gateway LLM router that saves <!-- br:savings.autoVsBaselinePct -->87<!-- /br:savings.autoVsBaselinePct -->% on inference costs by forwarding each request to the blockrun.ai gateway, which picks the cheapest model capable of handling it across <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> models from 9 providers (<!-- br:models.free -->8<!-- /br:models.free --> free NVIDIA models). All billing flows through one USDC wallet; you do not hold provider API keys.
57
57
 
58
58
  **This is not a local-inference tool.** ClawRouter is a thin local proxy. Your prompts are sent over HTTPS to the blockrun.ai gateway for model execution. If your workload requires inference that never leaves your machine, use a local runtime like Ollama — ClawRouter is not the right tool for that use case.
59
59
 
@@ -126,16 +126,22 @@ openclaw models set openai/gpt-4o
126
126
 
127
127
  ClawRouter classifies each request into one of four tiers:
128
128
 
129
- - **SIMPLE** (40% of traffic) — factual lookups, greetings, translations → Gemini Flash ($0.60/M, 99% savings)
130
- - **MEDIUM** (30%) — summaries, explanations, data extraction → DeepSeek Chat ($0.42/M, 99% savings)
131
- - **COMPLEX** (20%) — code generation, multi-step analysis → Claude Opus ($75/M, best quality)
132
- - **REASONING** (10%) — proofs, formal logic, multi-step math → o3 ($8/M, 89% savings)
129
+ - **SIMPLE** — factual lookups, greetings, translations → gemini-2.5-flash ($0.30/$2.50)
130
+ - **MEDIUM** — summaries, explanations, data extraction → kimi-k2.7 ($0.95/$4.00)
131
+ - **COMPLEX** — code generation, multi-step analysis → gemini-3.1-pro ($2/$12)
132
+ - **REASONING** — proofs, formal logic, multi-step math → grok-4-1-fast-reasoning ($0.20/$0.50)
133
+
134
+ Prices are per 1M input/output tokens, on the default `auto` profile. Per-tier
135
+ savings percentages are deliberately not quoted here: the published figure is
136
+ blended across a stated workload mix, and a per-tier number invites comparing
137
+ it against a baseline nobody wrote down. See
138
+ [savings-mix.json](https://github.com/BlockRunAI/blockrun/blob/main/src/brand/savings-mix.json).
133
139
 
134
140
  Rules handle ~~80% of requests in <1ms. Only ambiguous queries hit the LLM classifier (~~$0.00003 per classification).
135
141
 
136
142
  ## Available Models
137
143
 
138
- 55+ models including: gpt-5.6-terra [balanced, stable default], gpt-5.6-sol [flagship], gpt-5.6-luna [cost-efficient], 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-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], and 8 free NVIDIA models (mistral-large-3-675b [default, 675B flagship], deepseek-v4-flash [1M context], seed-oss-36b [coding], nemotron-3-nano-omni-30b-a3b-reasoning [vision], mistral-nemotron, step-3.7-flash, nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl [vision]).
144
+ <!-- br:models.chatVisible -->66<!-- /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.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-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], and 8 free NVIDIA models (mistral-large-3-675b [default, 675B flagship], deepseek-v4-flash [1M context], seed-oss-36b [coding], nemotron-3-nano-omni-30b-a3b-reasoning [vision], mistral-nemotron, step-3.7-flash, nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl [vision]).
139
145
 
140
146
  ## Built-in Agent Tools
141
147