@blockrun/clawrouter 0.12.64 → 0.12.66

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,31 @@ 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
+ });
49103
+ const isPaymentErr = /payment.*verification.*failed|payment.*settlement.*failed|insufficient.*funds|transaction_simulation_failed/i.test(
49104
+ result.errorBody || ""
49105
+ );
49106
+ if (isPaymentErr && tryModel !== FREE_MODEL && !isLastAttempt) {
49107
+ failedAttempts.push({
49108
+ ...failedAttempts[failedAttempts.length - 1],
49109
+ reason: "payment_error"
49110
+ });
49111
+ const freeIdx = modelsToTry.indexOf(FREE_MODEL);
49112
+ if (freeIdx > i + 1) {
49113
+ console.log(`[ClawRouter] Payment error \u2014 skipping to free model: ${FREE_MODEL}`);
49114
+ i = freeIdx - 1;
49115
+ continue;
49116
+ }
49117
+ if (freeIdx === -1) {
49118
+ modelsToTry.push(FREE_MODEL);
49119
+ console.log(`[ClawRouter] Payment error \u2014 appending free model: ${FREE_MODEL}`);
49120
+ continue;
49121
+ }
49122
+ }
49091
49123
  if (result.isProviderError && !isLastAttempt) {
49092
49124
  const isExplicitModelError = !routingDecision;
49093
49125
  const isUnknownExplicitModel = isExplicitModelError && /unknown.*model|invalid.*model/i.test(result.errorBody || "");
@@ -49165,17 +49197,6 @@ data: [DONE]
49165
49197
  `[ClawRouter] \u{1F511} ${errorCat === "auth_failure" ? "Auth failure" : "Quota exceeded"} for ${tryModel} \u2014 check provider config`
49166
49198
  );
49167
49199
  }
49168
- const isPaymentErr = /payment.*verification.*failed|payment.*settlement.*failed|insufficient.*funds|transaction_simulation_failed/i.test(
49169
- result.errorBody || ""
49170
- );
49171
- if (isPaymentErr && tryModel !== FREE_MODEL) {
49172
- const freeIdx = modelsToTry.indexOf(FREE_MODEL);
49173
- if (freeIdx > i + 1) {
49174
- console.log(`[ClawRouter] Payment error \u2014 skipping to free model: ${FREE_MODEL}`);
49175
- i = freeIdx - 1;
49176
- continue;
49177
- }
49178
- }
49179
49200
  console.log(
49180
49201
  `[ClawRouter] Provider error from ${tryModel}, trying fallback: ${result.errorBody?.slice(0, 100)}`
49181
49202
  );
@@ -49225,7 +49246,10 @@ data: [DONE]
49225
49246
  }
49226
49247
  }
49227
49248
  if (!upstream) {
49228
- const rawErrBody = lastError?.body || "All models in fallback chain failed";
49249
+ const attemptSummary = failedAttempts.length > 0 ? failedAttempts.map((a) => `${a.model} (${a.reason})`).join(", ") : "unknown";
49250
+ const structuredMessage = failedAttempts.length > 0 ? `All ${failedAttempts.length} models failed. Tried: ${attemptSummary}` : "All models in fallback chain failed";
49251
+ console.log(`[ClawRouter] ${structuredMessage}`);
49252
+ const rawErrBody = lastError?.body || structuredMessage;
49229
49253
  const errStatus = lastError?.status || 502;
49230
49254
  const transformedErr = transformPaymentError(rawErrBody);
49231
49255
  if (headersSentEarly) {
@@ -49284,7 +49308,7 @@ data: [DONE]
49284
49308
  id: rsp.id ?? `chatcmpl-${Date.now()}`,
49285
49309
  object: "chat.completion.chunk",
49286
49310
  created: rsp.created ?? Math.floor(Date.now() / 1e3),
49287
- model: rsp.model ?? "unknown",
49311
+ model: actualModelUsed || rsp.model || "unknown",
49288
49312
  system_fingerprint: null
49289
49313
  };
49290
49314
  if (rsp.choices && Array.isArray(rsp.choices)) {
@@ -49399,6 +49423,13 @@ data: [DONE]
49399
49423
  responseChunks.push(Buffer.from(sseData));
49400
49424
  }
49401
49425
  }
49426
+ if (routingDecision) {
49427
+ const costComment = `: cost=$${routingDecision.costEstimate.toFixed(4)} savings=${(routingDecision.savings * 100).toFixed(0)}% model=${actualModelUsed} tier=${routingDecision.tier}
49428
+
49429
+ `;
49430
+ safeWrite(res, costComment);
49431
+ responseChunks.push(Buffer.from(costComment));
49432
+ }
49402
49433
  safeWrite(res, "data: [DONE]\n\n");
49403
49434
  responseChunks.push(Buffer.from("data: [DONE]\n\n"));
49404
49435
  res.end();
@@ -49427,6 +49458,10 @@ data: [DONE]
49427
49458
  responseHeaders["x-clawrouter-agentic-score"] = routingDecision.agenticScore.toFixed(2);
49428
49459
  }
49429
49460
  }
49461
+ if (routingDecision) {
49462
+ responseHeaders["x-clawrouter-cost"] = routingDecision.costEstimate.toFixed(6);
49463
+ responseHeaders["x-clawrouter-savings"] = `${(routingDecision.savings * 100).toFixed(0)}%`;
49464
+ }
49430
49465
  const bodyParts = [];
49431
49466
  if (upstream.body) {
49432
49467
  const chunks = await readBodyWithTimeout(upstream.body);
@@ -49457,6 +49492,16 @@ data: [DONE]
49457
49492
  }
49458
49493
  budgetDowngradeNotice = void 0;
49459
49494
  }
49495
+ if (actualModelUsed && responseBody.length > 0) {
49496
+ try {
49497
+ const parsed = JSON.parse(responseBody.toString());
49498
+ if (parsed.model !== void 0) {
49499
+ parsed.model = actualModelUsed;
49500
+ responseBody = Buffer.from(JSON.stringify(parsed));
49501
+ }
49502
+ } catch {
49503
+ }
49504
+ }
49460
49505
  if (budgetDowngradeHeaderMode) {
49461
49506
  responseHeaders["x-clawrouter-budget-downgrade"] = "1";
49462
49507
  responseHeaders["x-clawrouter-budget-mode"] = budgetDowngradeHeaderMode;