@blockrun/clawrouter 0.12.64 → 0.12.65

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
@@ -108,11 +108,11 @@ Choose your routing strategy with `/model <profile>`:
108
108
  Request → Weighted Scorer (15 dimensions) → Tier → Best Model → Response
109
109
  ```
110
110
 
111
- | Tier | ECO Model | AUTO Model | PREMIUM Model |
112
- | --------- | ----------------------------------- | ---------------------------------- | ---------------------------- |
113
- | SIMPLE | nvidia/gpt-oss-120b (FREE) | kimi-k2.5 ($0.60/$3.00) | kimi-k2.5 |
114
- | MEDIUM | gemini-2.5-flash-lite ($0.10/$0.40) | grok-4-0709 ($0.20/$1.50) | gpt-5.3-codex ($1.75/$14.00) |
115
- | COMPLEX | gemini-2.5-flash-lite ($0.10/$0.40) | gemini-3.1-pro ($2/$12) | claude-opus-4.6 ($5/$25) |
111
+ | Tier | ECO Model | AUTO Model | PREMIUM Model |
112
+ | --------- | ----------------------------------- | ------------------------------------- | ---------------------------- |
113
+ | SIMPLE | nvidia/gpt-oss-120b (FREE) | kimi-k2.5 ($0.60/$3.00) | kimi-k2.5 |
114
+ | MEDIUM | gemini-2.5-flash-lite ($0.10/$0.40) | grok-4-0709 ($0.20/$1.50) | gpt-5.3-codex ($1.75/$14.00) |
115
+ | COMPLEX | gemini-2.5-flash-lite ($0.10/$0.40) | gemini-3.1-pro ($2/$12) | claude-opus-4.6 ($5/$25) |
116
116
  | REASONING | grok-4-fast ($0.20/$0.50) | grok-4-1-fast-reasoning ($0.20/$0.50) | claude-sonnet-4.6 ($3/$15) |
117
117
 
118
118
  **Blended average: $2.05/M** vs $25/M for Claude Opus = **92% savings**
@@ -165,62 +165,62 @@ Edit existing images with `/img2img`:
165
165
 
166
166
  ### Budget Models (under $0.001/request)
167
167
 
168
- | Model | Input $/M | Output $/M | ~$/request | Context | Features |
169
- | --- | ---: | ---: | ---: | --- | --- |
170
- | nvidia/gpt-oss-120b | **FREE** | **FREE** | **$0** | 128K | |
171
- | openai/gpt-5-nano | $0.05 | $0.40 | $0.0002 | 128K | tools |
172
- | openai/gpt-4.1-nano | $0.10 | $0.40 | $0.0003 | 128K | tools |
173
- | google/gemini-2.5-flash-lite | $0.10 | $0.40 | $0.0003 | 1M | tools |
174
- | openai/gpt-4o-mini | $0.15 | $0.60 | $0.0004 | 128K | tools |
175
- | xai/grok-4-fast | $0.20 | $0.50 | $0.0004 | 131K | tools |
176
- | xai/grok-4-fast-reasoning | $0.20 | $0.50 | $0.0004 | 131K | reasoning, tools |
177
- | xai/grok-4-1-fast | $0.20 | $0.50 | $0.0004 | 131K | tools |
178
- | xai/grok-4-1-fast-reasoning | $0.20 | $0.50 | $0.0004 | 131K | reasoning, tools |
179
- | xai/grok-4-0709 | $0.20 | $1.50 | $0.0009 | 131K | reasoning, tools |
180
- | openai/gpt-5-mini | $0.25 | $2.00 | $0.0011 | 200K | tools |
181
- | deepseek/deepseek-chat | $0.28 | $0.42 | $0.0004 | 128K | tools |
182
- | deepseek/deepseek-reasoner | $0.28 | $0.42 | $0.0004 | 128K | reasoning, tools |
183
- | xai/grok-3-mini | $0.30 | $0.50 | $0.0004 | 131K | tools |
184
- | minimax/minimax-m2.7 | $0.30 | $1.20 | $0.0008 | 205K | reasoning, agentic, tools |
185
- | minimax/minimax-m2.5 | $0.30 | $1.20 | $0.0008 | 205K | reasoning, agentic, tools |
186
- | google/gemini-2.5-flash | $0.30 | $2.50 | $0.0014 | 1M | vision, tools |
187
- | openai/gpt-4.1-mini | $0.40 | $1.60 | $0.0010 | 128K | tools |
188
- | google/gemini-3-flash-preview | $0.50 | $3.00 | $0.0018 | 1M | vision |
189
- | nvidia/kimi-k2.5 | $0.55 | $2.50 | $0.0015 | 262K | tools |
190
- | moonshot/kimi-k2.5 | $0.60 | $3.00 | $0.0018 | 262K | reasoning, vision, agentic, tools |
168
+ | Model | Input $/M | Output $/M | ~$/request | Context | Features |
169
+ | ----------------------------- | --------: | ---------: | ---------: | ------- | --------------------------------- |
170
+ | nvidia/gpt-oss-120b | **FREE** | **FREE** | **$0** | 128K | |
171
+ | openai/gpt-5-nano | $0.05 | $0.40 | $0.0002 | 128K | tools |
172
+ | openai/gpt-4.1-nano | $0.10 | $0.40 | $0.0003 | 128K | tools |
173
+ | google/gemini-2.5-flash-lite | $0.10 | $0.40 | $0.0003 | 1M | tools |
174
+ | openai/gpt-4o-mini | $0.15 | $0.60 | $0.0004 | 128K | tools |
175
+ | xai/grok-4-fast | $0.20 | $0.50 | $0.0004 | 131K | tools |
176
+ | xai/grok-4-fast-reasoning | $0.20 | $0.50 | $0.0004 | 131K | reasoning, tools |
177
+ | xai/grok-4-1-fast | $0.20 | $0.50 | $0.0004 | 131K | tools |
178
+ | xai/grok-4-1-fast-reasoning | $0.20 | $0.50 | $0.0004 | 131K | reasoning, tools |
179
+ | xai/grok-4-0709 | $0.20 | $1.50 | $0.0009 | 131K | reasoning, tools |
180
+ | openai/gpt-5-mini | $0.25 | $2.00 | $0.0011 | 200K | tools |
181
+ | deepseek/deepseek-chat | $0.28 | $0.42 | $0.0004 | 128K | tools |
182
+ | deepseek/deepseek-reasoner | $0.28 | $0.42 | $0.0004 | 128K | reasoning, tools |
183
+ | xai/grok-3-mini | $0.30 | $0.50 | $0.0004 | 131K | tools |
184
+ | minimax/minimax-m2.7 | $0.30 | $1.20 | $0.0008 | 205K | reasoning, agentic, tools |
185
+ | minimax/minimax-m2.5 | $0.30 | $1.20 | $0.0008 | 205K | reasoning, agentic, tools |
186
+ | google/gemini-2.5-flash | $0.30 | $2.50 | $0.0014 | 1M | vision, tools |
187
+ | openai/gpt-4.1-mini | $0.40 | $1.60 | $0.0010 | 128K | tools |
188
+ | google/gemini-3-flash-preview | $0.50 | $3.00 | $0.0018 | 1M | vision |
189
+ | nvidia/kimi-k2.5 | $0.55 | $2.50 | $0.0015 | 262K | tools |
190
+ | moonshot/kimi-k2.5 | $0.60 | $3.00 | $0.0018 | 262K | reasoning, vision, agentic, tools |
191
191
 
192
192
  ### Mid-Range Models ($0.001–$0.01/request)
193
193
 
194
- | Model | Input $/M | Output $/M | ~$/request | Context | Features |
195
- | --- | ---: | ---: | ---: | --- | --- |
196
- | anthropic/claude-haiku-4.5 | $1.00 | $5.00 | $0.0030 | 200K | vision, agentic, tools |
197
- | zai/glm-5 | $1.00 | $3.20 | $0.0021 | 200K | tools |
198
- | openai/o1-mini | $1.10 | $4.40 | $0.0028 | 128K | reasoning, tools |
199
- | openai/o3-mini | $1.10 | $4.40 | $0.0028 | 128K | reasoning, tools |
200
- | openai/o4-mini | $1.10 | $4.40 | $0.0028 | 128K | reasoning, tools |
201
- | zai/glm-5-turbo | $1.20 | $4.00 | $0.0026 | 200K | tools |
202
- | google/gemini-2.5-pro | $1.25 | $10.00 | $0.0056 | 1M | reasoning, vision, tools |
203
- | openai/gpt-5.2 | $1.75 | $14.00 | $0.0079 | 400K | reasoning, vision, agentic, tools |
204
- | openai/gpt-5.3 | $1.75 | $14.00 | $0.0079 | 128K | reasoning, vision, agentic, tools |
205
- | openai/gpt-5.3-codex | $1.75 | $14.00 | $0.0079 | 400K | agentic, tools |
206
- | openai/gpt-4.1 | $2.00 | $8.00 | $0.0050 | 128K | vision, tools |
207
- | openai/o3 | $2.00 | $8.00 | $0.0050 | 200K | reasoning, tools |
208
- | google/gemini-3-pro-preview | $2.00 | $12.00 | $0.0070 | 1M | reasoning, vision, tools |
209
- | google/gemini-3.1-pro | $2.00 | $12.00 | $0.0070 | 1M | reasoning, vision, tools |
210
- | xai/grok-2-vision | $2.00 | $10.00 | $0.0060 | 131K | vision, tools |
211
- | openai/gpt-4o | $2.50 | $10.00 | $0.0063 | 128K | vision, agentic, tools |
212
- | openai/gpt-5.4 | $2.50 | $15.00 | $0.0088 | 400K | reasoning, vision, agentic, tools |
194
+ | Model | Input $/M | Output $/M | ~$/request | Context | Features |
195
+ | --------------------------- | --------: | ---------: | ---------: | ------- | --------------------------------- |
196
+ | anthropic/claude-haiku-4.5 | $1.00 | $5.00 | $0.0030 | 200K | vision, agentic, tools |
197
+ | zai/glm-5 | $1.00 | $3.20 | $0.0021 | 200K | tools |
198
+ | openai/o1-mini | $1.10 | $4.40 | $0.0028 | 128K | reasoning, tools |
199
+ | openai/o3-mini | $1.10 | $4.40 | $0.0028 | 128K | reasoning, tools |
200
+ | openai/o4-mini | $1.10 | $4.40 | $0.0028 | 128K | reasoning, tools |
201
+ | zai/glm-5-turbo | $1.20 | $4.00 | $0.0026 | 200K | tools |
202
+ | google/gemini-2.5-pro | $1.25 | $10.00 | $0.0056 | 1M | reasoning, vision, tools |
203
+ | openai/gpt-5.2 | $1.75 | $14.00 | $0.0079 | 400K | reasoning, vision, agentic, tools |
204
+ | openai/gpt-5.3 | $1.75 | $14.00 | $0.0079 | 128K | reasoning, vision, agentic, tools |
205
+ | openai/gpt-5.3-codex | $1.75 | $14.00 | $0.0079 | 400K | agentic, tools |
206
+ | openai/gpt-4.1 | $2.00 | $8.00 | $0.0050 | 128K | vision, tools |
207
+ | openai/o3 | $2.00 | $8.00 | $0.0050 | 200K | reasoning, tools |
208
+ | google/gemini-3-pro-preview | $2.00 | $12.00 | $0.0070 | 1M | reasoning, vision, tools |
209
+ | google/gemini-3.1-pro | $2.00 | $12.00 | $0.0070 | 1M | reasoning, vision, tools |
210
+ | xai/grok-2-vision | $2.00 | $10.00 | $0.0060 | 131K | vision, tools |
211
+ | openai/gpt-4o | $2.50 | $10.00 | $0.0063 | 128K | vision, agentic, tools |
212
+ | openai/gpt-5.4 | $2.50 | $15.00 | $0.0088 | 400K | reasoning, vision, agentic, tools |
213
213
 
214
214
  ### Premium Models ($0.01+/request)
215
215
 
216
- | Model | Input $/M | Output $/M | ~$/request | Context | Features |
217
- | --- | ---: | ---: | ---: | --- | --- |
218
- | anthropic/claude-sonnet-4.6 | $3.00 | $15.00 | $0.0090 | 200K | reasoning, vision, agentic, tools |
219
- | xai/grok-3 | $3.00 | $15.00 | $0.0090 | 131K | reasoning, tools |
220
- | anthropic/claude-opus-4.6 | $5.00 | $25.00 | $0.0150 | 200K | reasoning, vision, agentic, tools |
221
- | openai/o1 | $15.00 | $60.00 | $0.0375 | 200K | reasoning, tools |
222
- | openai/gpt-5.2-pro | $21.00 | $168.00 | $0.0945 | 400K | reasoning, tools |
223
- | openai/gpt-5.4-pro | $30.00 | $180.00 | $0.1050 | 400K | reasoning, tools |
216
+ | Model | Input $/M | Output $/M | ~$/request | Context | Features |
217
+ | --------------------------- | --------: | ---------: | ---------: | ------- | --------------------------------- |
218
+ | anthropic/claude-sonnet-4.6 | $3.00 | $15.00 | $0.0090 | 200K | reasoning, vision, agentic, tools |
219
+ | xai/grok-3 | $3.00 | $15.00 | $0.0090 | 131K | reasoning, tools |
220
+ | anthropic/claude-opus-4.6 | $5.00 | $25.00 | $0.0150 | 200K | reasoning, vision, agentic, tools |
221
+ | openai/o1 | $15.00 | $60.00 | $0.0375 | 200K | reasoning, tools |
222
+ | openai/gpt-5.2-pro | $21.00 | $168.00 | $0.0945 | 400K | reasoning, tools |
223
+ | openai/gpt-5.4-pro | $30.00 | $180.00 | $0.1050 | 400K | reasoning, tools |
224
224
 
225
225
  > **Free tier:** `nvidia/gpt-oss-120b` costs nothing and serves as automatic fallback when wallet is empty.
226
226
  > **Best value:** `gpt-5-nano` and `gemini-2.5-flash-lite` deliver strong results at ~$0.0003/request.
package/dist/cli.js CHANGED
@@ -37975,7 +37975,19 @@ function createPayFetchWithPreAuth(baseFetch, client, ttlMs = DEFAULT_TTL_MS, op
37975
37975
  return async (input, init) => {
37976
37976
  const request = new Request(input, init);
37977
37977
  const urlPath = new URL(request.url).pathname;
37978
- const cached = !options?.skipPreAuth ? cache2.get(urlPath) : void 0;
37978
+ let requestModel = "";
37979
+ if (init?.body) {
37980
+ try {
37981
+ const bodyStr = init.body instanceof Uint8Array ? new TextDecoder().decode(init.body) : typeof init.body === "string" ? init.body : "";
37982
+ if (bodyStr) {
37983
+ const parsed = JSON.parse(bodyStr);
37984
+ requestModel = parsed.model ?? "";
37985
+ }
37986
+ } catch {
37987
+ }
37988
+ }
37989
+ const cacheKey2 = `${urlPath}:${requestModel}`;
37990
+ const cached = !options?.skipPreAuth ? cache2.get(cacheKey2) : void 0;
37979
37991
  if (cached && Date.now() - cached.cachedAt < ttlMs) {
37980
37992
  try {
37981
37993
  const payload2 = await client.createPaymentPayload(cached.paymentRequired);
@@ -37988,9 +38000,9 @@ function createPayFetchWithPreAuth(baseFetch, client, ttlMs = DEFAULT_TTL_MS, op
37988
38000
  if (response2.status !== 402) {
37989
38001
  return response2;
37990
38002
  }
37991
- cache2.delete(urlPath);
38003
+ cache2.delete(cacheKey2);
37992
38004
  } catch {
37993
- cache2.delete(urlPath);
38005
+ cache2.delete(cacheKey2);
37994
38006
  }
37995
38007
  }
37996
38008
  const clonedRequest = request.clone();
@@ -38013,7 +38025,7 @@ function createPayFetchWithPreAuth(baseFetch, client, ttlMs = DEFAULT_TTL_MS, op
38013
38025
  } catch {
38014
38026
  }
38015
38027
  paymentRequired = httpClient.getPaymentRequiredResponse(getHeader, body);
38016
- cache2.set(urlPath, { paymentRequired, cachedAt: Date.now() });
38028
+ cache2.set(cacheKey2, { paymentRequired, cachedAt: Date.now() });
38017
38029
  } catch (error) {
38018
38030
  throw new Error(
38019
38031
  `Failed to parse payment requirements: ${error instanceof Error ? error.message : "Unknown error"}`,
@@ -46367,12 +46379,7 @@ async function checkForUpdates() {
46367
46379
  import { readFileSync, writeFileSync, mkdirSync } from "fs";
46368
46380
  import { join as join7, dirname as dirname2 } from "path";
46369
46381
  import { homedir as homedir4 } from "os";
46370
- var DEFAULT_FILE_PATH = join7(
46371
- homedir4(),
46372
- ".openclaw",
46373
- "blockrun",
46374
- "exclude-models.json"
46375
- );
46382
+ var DEFAULT_FILE_PATH = join7(homedir4(), ".openclaw", "blockrun", "exclude-models.json");
46376
46383
  function loadExcludeList(filePath = DEFAULT_FILE_PATH) {
46377
46384
  try {
46378
46385
  const raw = readFileSync(filePath, "utf-8");
@@ -46752,8 +46759,7 @@ function categorizeError(status, body) {
46752
46759
  if (status === 401) return "auth_failure";
46753
46760
  if (status === 402) return "payment_error";
46754
46761
  if (status === 403) {
46755
- if (/plan.*limit|quota.*exceeded|subscription|allowance/i.test(body))
46756
- return "quota_exceeded";
46762
+ if (/plan.*limit|quota.*exceeded|subscription|allowance/i.test(body)) return "quota_exceeded";
46757
46763
  return "auth_failure";
46758
46764
  }
46759
46765
  if (status === 429) return "rate_limited";
@@ -49040,6 +49046,7 @@ data: [DONE]
49040
49046
  let upstream;
49041
49047
  let lastError;
49042
49048
  let actualModelUsed = modelId;
49049
+ const failedAttempts = [];
49043
49050
  for (let i = 0; i < modelsToTry.length; i++) {
49044
49051
  const tryModel = modelsToTry[i];
49045
49052
  const isLastAttempt = i === modelsToTry.length - 1;
@@ -49088,6 +49095,11 @@ data: [DONE]
49088
49095
  body: result.errorBody || "Unknown error",
49089
49096
  status: result.errorStatus || 500
49090
49097
  };
49098
+ failedAttempts.push({
49099
+ model: tryModel,
49100
+ reason: result.errorCategory || `HTTP ${result.errorStatus || 500}`,
49101
+ status: result.errorStatus || 500
49102
+ });
49091
49103
  if (result.isProviderError && !isLastAttempt) {
49092
49104
  const isExplicitModelError = !routingDecision;
49093
49105
  const isUnknownExplicitModel = isExplicitModelError && /unknown.*model|invalid.*model/i.test(result.errorBody || "");
@@ -49225,7 +49237,10 @@ data: [DONE]
49225
49237
  }
49226
49238
  }
49227
49239
  if (!upstream) {
49228
- const rawErrBody = lastError?.body || "All models in fallback chain failed";
49240
+ const attemptSummary = failedAttempts.length > 0 ? failedAttempts.map((a) => `${a.model} (${a.reason})`).join(", ") : "unknown";
49241
+ const structuredMessage = failedAttempts.length > 0 ? `All ${failedAttempts.length} models failed. Tried: ${attemptSummary}` : "All models in fallback chain failed";
49242
+ console.log(`[ClawRouter] ${structuredMessage}`);
49243
+ const rawErrBody = lastError?.body || structuredMessage;
49229
49244
  const errStatus = lastError?.status || 502;
49230
49245
  const transformedErr = transformPaymentError(rawErrBody);
49231
49246
  if (headersSentEarly) {
@@ -49284,7 +49299,7 @@ data: [DONE]
49284
49299
  id: rsp.id ?? `chatcmpl-${Date.now()}`,
49285
49300
  object: "chat.completion.chunk",
49286
49301
  created: rsp.created ?? Math.floor(Date.now() / 1e3),
49287
- model: rsp.model ?? "unknown",
49302
+ model: actualModelUsed || rsp.model || "unknown",
49288
49303
  system_fingerprint: null
49289
49304
  };
49290
49305
  if (rsp.choices && Array.isArray(rsp.choices)) {
@@ -49399,6 +49414,13 @@ data: [DONE]
49399
49414
  responseChunks.push(Buffer.from(sseData));
49400
49415
  }
49401
49416
  }
49417
+ if (routingDecision) {
49418
+ const costComment = `: cost=$${routingDecision.costEstimate.toFixed(4)} savings=${(routingDecision.savings * 100).toFixed(0)}% model=${actualModelUsed} tier=${routingDecision.tier}
49419
+
49420
+ `;
49421
+ safeWrite(res, costComment);
49422
+ responseChunks.push(Buffer.from(costComment));
49423
+ }
49402
49424
  safeWrite(res, "data: [DONE]\n\n");
49403
49425
  responseChunks.push(Buffer.from("data: [DONE]\n\n"));
49404
49426
  res.end();
@@ -49427,6 +49449,10 @@ data: [DONE]
49427
49449
  responseHeaders["x-clawrouter-agentic-score"] = routingDecision.agenticScore.toFixed(2);
49428
49450
  }
49429
49451
  }
49452
+ if (routingDecision) {
49453
+ responseHeaders["x-clawrouter-cost"] = routingDecision.costEstimate.toFixed(6);
49454
+ responseHeaders["x-clawrouter-savings"] = `${(routingDecision.savings * 100).toFixed(0)}%`;
49455
+ }
49430
49456
  const bodyParts = [];
49431
49457
  if (upstream.body) {
49432
49458
  const chunks = await readBodyWithTimeout(upstream.body);
@@ -49457,6 +49483,16 @@ data: [DONE]
49457
49483
  }
49458
49484
  budgetDowngradeNotice = void 0;
49459
49485
  }
49486
+ if (actualModelUsed && responseBody.length > 0) {
49487
+ try {
49488
+ const parsed = JSON.parse(responseBody.toString());
49489
+ if (parsed.model !== void 0) {
49490
+ parsed.model = actualModelUsed;
49491
+ responseBody = Buffer.from(JSON.stringify(parsed));
49492
+ }
49493
+ } catch {
49494
+ }
49495
+ }
49460
49496
  if (budgetDowngradeHeaderMode) {
49461
49497
  responseHeaders["x-clawrouter-budget-downgrade"] = "1";
49462
49498
  responseHeaders["x-clawrouter-budget-mode"] = budgetDowngradeHeaderMode;