@blockrun/clawrouter 0.12.252 → 0.12.254

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.
Files changed (3) hide show
  1. package/dist/cli.js +37 -12
  2. package/dist/index.js +37 -12
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -90607,6 +90607,10 @@ async function startProxy(options) {
90607
90607
  }
90608
90608
  if (req.url === "/v1/audio/generations" && req.method === "POST") {
90609
90609
  const audioStartTime = Date.now();
90610
+ const clientAbort = new AbortController();
90611
+ res.on("close", () => {
90612
+ if (!res.writableEnded) clientAbort.abort();
90613
+ });
90610
90614
  const chunks = [];
90611
90615
  for await (const chunk of req) {
90612
90616
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
@@ -90622,7 +90626,8 @@ async function startProxy(options) {
90622
90626
  const upstream = await payFetch(`${apiBase}/v1/audio/generations`, {
90623
90627
  method: "POST",
90624
90628
  headers: { "content-type": "application/json", "user-agent": USER_AGENT },
90625
- body: reqBody
90629
+ body: reqBody,
90630
+ signal: clientAbort.signal
90626
90631
  });
90627
90632
  const text = await upstream.text();
90628
90633
  if (!upstream.ok) {
@@ -90644,7 +90649,7 @@ async function startProxy(options) {
90644
90649
  for (const track of result.data) {
90645
90650
  if (track.url?.startsWith("https://") || track.url?.startsWith("http://")) {
90646
90651
  try {
90647
- const audioResp = await fetch(track.url);
90652
+ const audioResp = await fetch(track.url, { signal: clientAbort.signal });
90648
90653
  if (audioResp.ok) {
90649
90654
  const contentType = audioResp.headers.get("content-type") ?? "audio/mpeg";
90650
90655
  const ext = contentType.includes("wav") ? "wav" : "mp3";
@@ -90676,6 +90681,7 @@ async function startProxy(options) {
90676
90681
  res.writeHead(200, { "Content-Type": "application/json" });
90677
90682
  res.end(JSON.stringify(result));
90678
90683
  } catch (err) {
90684
+ if (clientAbort.signal.aborted) return;
90679
90685
  const msg = err instanceof Error ? err.message : String(err);
90680
90686
  console.error(`[ClawRouter] Audio generation error: ${msg}`);
90681
90687
  if (!res.headersSent) {
@@ -91695,6 +91701,10 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91695
91701
  console.log(
91696
91702
  `[ClawRouter] /img2img \u2192 ${img2imgModel} (${img2imgSize}): ${img2imgPrompt.slice(0, 80)}`
91697
91703
  );
91704
+ const img2imgAbort = new AbortController();
91705
+ res.on("close", () => {
91706
+ if (!res.writableEnded) img2imgAbort.abort();
91707
+ });
91698
91708
  try {
91699
91709
  const img2imgBody = JSON.stringify({
91700
91710
  model: img2imgModel,
@@ -91707,7 +91717,8 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91707
91717
  const img2imgResponse = await payFetch(`${apiBase}/v1/images/image2image`, {
91708
91718
  method: "POST",
91709
91719
  headers: { "content-type": "application/json", "user-agent": USER_AGENT },
91710
- body: img2imgBody
91720
+ body: img2imgBody,
91721
+ signal: img2imgAbort.signal
91711
91722
  });
91712
91723
  const img2imgResult = await img2imgResponse.json();
91713
91724
  let responseText;
@@ -91757,6 +91768,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91757
91768
  }
91758
91769
  sendImg2ImgText(responseText);
91759
91770
  } catch (err) {
91771
+ if (img2imgAbort.signal.aborted) return;
91760
91772
  const errMsg = err instanceof Error ? err.message : String(err);
91761
91773
  console.error(`[ClawRouter] /img2img error: ${errMsg}`);
91762
91774
  if (!res.headersSent) {
@@ -92308,13 +92320,16 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
92308
92320
  const timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
92309
92321
  const globalController = new AbortController();
92310
92322
  const timeoutId = setTimeout(() => globalController.abort(), timeoutMs);
92323
+ const clientDisconnected = () => res.destroyed && !res.writableEnded;
92324
+ const abortError = () => clientDisconnected() ? new ClientDisconnectedError() : new Error(`Request timed out after ${timeoutMs}ms`);
92311
92325
  const onClientClose = () => {
92312
- if (!globalController.signal.aborted) {
92326
+ if (!res.writableEnded && !globalController.signal.aborted) {
92313
92327
  console.log(`[ClawRouter] Client disconnected \u2014 aborting upstream request`);
92314
92328
  globalController.abort();
92315
92329
  }
92316
92330
  };
92317
- req.on("close", onClientClose);
92331
+ res.on("close", onClientClose);
92332
+ if (res.destroyed) onClientClose();
92318
92333
  try {
92319
92334
  let modelsToTry;
92320
92335
  const excludeList = options.excludeModels ?? loadExcludeList();
@@ -92373,7 +92388,7 @@ data: [DONE]
92373
92388
  completed = true;
92374
92389
  deduplicator.removeInflight(dedupKey);
92375
92390
  clearTimeout(timeoutId);
92376
- req.removeListener("close", onClientClose);
92391
+ res.removeListener("close", onClientClose);
92377
92392
  return;
92378
92393
  }
92379
92394
  const contextExcluded = fullChain.filter((m) => !contextFiltered.includes(m));
@@ -92472,7 +92487,7 @@ data: [DONE]
92472
92487
  }
92473
92488
  deduplicator.removeInflight(dedupKey);
92474
92489
  clearTimeout(timeoutId);
92475
- req.removeListener("close", onClientClose);
92490
+ res.removeListener("close", onClientClose);
92476
92491
  return;
92477
92492
  }
92478
92493
  if (excluded.length > 0) {
@@ -92503,7 +92518,7 @@ data: [DONE]
92503
92518
  const tryModel = modelsToTry[i];
92504
92519
  const isLastAttempt = i === modelsToTry.length - 1;
92505
92520
  if (globalController.signal.aborted) {
92506
- throw new Error(`Request timed out after ${timeoutMs}ms`);
92521
+ throw abortError();
92507
92522
  }
92508
92523
  console.log(`[ClawRouter] Trying model ${i + 1}/${modelsToTry.length}: ${tryModel}`);
92509
92524
  const perAttemptTimeoutMs = timeoutForModel(tryModel);
@@ -92523,7 +92538,7 @@ data: [DONE]
92523
92538
  );
92524
92539
  clearTimeout(modelTimeoutId);
92525
92540
  if (globalController.signal.aborted) {
92526
- throw new Error(`Request timed out after ${timeoutMs}ms`);
92541
+ throw abortError();
92527
92542
  }
92528
92543
  if (!result.success && modelController.signal.aborted && !isLastAttempt) {
92529
92544
  console.log(
@@ -92735,7 +92750,7 @@ data: [DONE]
92735
92750
  break;
92736
92751
  }
92737
92752
  clearTimeout(timeoutId);
92738
- req.removeListener("close", onClientClose);
92753
+ res.removeListener("close", onClientClose);
92739
92754
  if (heartbeatInterval) {
92740
92755
  clearInterval(heartbeatInterval);
92741
92756
  heartbeatInterval = void 0;
@@ -93238,12 +93253,16 @@ data: [DONE]
93238
93253
  completed = true;
93239
93254
  } catch (err) {
93240
93255
  clearTimeout(timeoutId);
93241
- req.removeListener("close", onClientClose);
93256
+ res.removeListener("close", onClientClose);
93242
93257
  if (heartbeatInterval) {
93243
93258
  clearInterval(heartbeatInterval);
93244
93259
  heartbeatInterval = void 0;
93245
93260
  }
93246
93261
  deduplicator.removeInflight(dedupKey);
93262
+ if (err instanceof ClientDisconnectedError || err instanceof Error && err.name === "AbortError" && clientDisconnected()) {
93263
+ console.log(`[ClawRouter] Request cancelled \u2014 client disconnected`);
93264
+ return;
93265
+ }
93247
93266
  balanceMonitor.invalidate();
93248
93267
  if (err instanceof Error && err.name === "AbortError") {
93249
93268
  throw new Error(`Request timed out after ${timeoutMs}ms`, { cause: err });
@@ -93299,7 +93318,7 @@ data: [DONE]
93299
93318
  });
93300
93319
  }
93301
93320
  }
93302
- 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, IMAGE_MODEL_IDS, IMAGE_MODEL_SIZES, IMAGE_MODEL_ALIASES, VIDEO_PRICING, PHONE_PRICING;
93321
+ 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, ClientDisconnectedError, 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, IMAGE_MODEL_IDS, IMAGE_MODEL_SIZES, IMAGE_MODEL_ALIASES, VIDEO_PRICING, PHONE_PRICING;
93303
93322
  var init_proxy = __esm({
93304
93323
  "src/proxy.ts"() {
93305
93324
  "use strict";
@@ -93379,6 +93398,12 @@ var init_proxy = __esm({
93379
93398
  PORT_RETRY_DELAY_MS = 1e3;
93380
93399
  MODEL_BODY_READ_TIMEOUT_MS = 3e5;
93381
93400
  ERROR_BODY_READ_TIMEOUT_MS = 3e4;
93401
+ ClientDisconnectedError = class extends Error {
93402
+ constructor() {
93403
+ super("Client disconnected");
93404
+ this.name = "ClientDisconnectedError";
93405
+ }
93406
+ };
93382
93407
  rateLimitedModels = /* @__PURE__ */ new Map();
93383
93408
  overloadedModels = /* @__PURE__ */ new Map();
93384
93409
  perProviderErrors = /* @__PURE__ */ new Map();
package/dist/index.js CHANGED
@@ -90427,6 +90427,10 @@ async function startProxy(options) {
90427
90427
  }
90428
90428
  if (req.url === "/v1/audio/generations" && req.method === "POST") {
90429
90429
  const audioStartTime = Date.now();
90430
+ const clientAbort = new AbortController();
90431
+ res.on("close", () => {
90432
+ if (!res.writableEnded) clientAbort.abort();
90433
+ });
90430
90434
  const chunks = [];
90431
90435
  for await (const chunk of req) {
90432
90436
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
@@ -90442,7 +90446,8 @@ async function startProxy(options) {
90442
90446
  const upstream = await payFetch(`${apiBase}/v1/audio/generations`, {
90443
90447
  method: "POST",
90444
90448
  headers: { "content-type": "application/json", "user-agent": USER_AGENT },
90445
- body: reqBody
90449
+ body: reqBody,
90450
+ signal: clientAbort.signal
90446
90451
  });
90447
90452
  const text = await upstream.text();
90448
90453
  if (!upstream.ok) {
@@ -90464,7 +90469,7 @@ async function startProxy(options) {
90464
90469
  for (const track of result.data) {
90465
90470
  if (track.url?.startsWith("https://") || track.url?.startsWith("http://")) {
90466
90471
  try {
90467
- const audioResp = await fetch(track.url);
90472
+ const audioResp = await fetch(track.url, { signal: clientAbort.signal });
90468
90473
  if (audioResp.ok) {
90469
90474
  const contentType = audioResp.headers.get("content-type") ?? "audio/mpeg";
90470
90475
  const ext = contentType.includes("wav") ? "wav" : "mp3";
@@ -90496,6 +90501,7 @@ async function startProxy(options) {
90496
90501
  res.writeHead(200, { "Content-Type": "application/json" });
90497
90502
  res.end(JSON.stringify(result));
90498
90503
  } catch (err) {
90504
+ if (clientAbort.signal.aborted) return;
90499
90505
  const msg = err instanceof Error ? err.message : String(err);
90500
90506
  console.error(`[ClawRouter] Audio generation error: ${msg}`);
90501
90507
  if (!res.headersSent) {
@@ -91515,6 +91521,10 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91515
91521
  console.log(
91516
91522
  `[ClawRouter] /img2img \u2192 ${img2imgModel} (${img2imgSize}): ${img2imgPrompt.slice(0, 80)}`
91517
91523
  );
91524
+ const img2imgAbort = new AbortController();
91525
+ res.on("close", () => {
91526
+ if (!res.writableEnded) img2imgAbort.abort();
91527
+ });
91518
91528
  try {
91519
91529
  const img2imgBody = JSON.stringify({
91520
91530
  model: img2imgModel,
@@ -91527,7 +91537,8 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91527
91537
  const img2imgResponse = await payFetch(`${apiBase}/v1/images/image2image`, {
91528
91538
  method: "POST",
91529
91539
  headers: { "content-type": "application/json", "user-agent": USER_AGENT },
91530
- body: img2imgBody
91540
+ body: img2imgBody,
91541
+ signal: img2imgAbort.signal
91531
91542
  });
91532
91543
  const img2imgResult = await img2imgResponse.json();
91533
91544
  let responseText;
@@ -91577,6 +91588,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91577
91588
  }
91578
91589
  sendImg2ImgText(responseText);
91579
91590
  } catch (err) {
91591
+ if (img2imgAbort.signal.aborted) return;
91580
91592
  const errMsg = err instanceof Error ? err.message : String(err);
91581
91593
  console.error(`[ClawRouter] /img2img error: ${errMsg}`);
91582
91594
  if (!res.headersSent) {
@@ -92128,13 +92140,16 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
92128
92140
  const timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
92129
92141
  const globalController = new AbortController();
92130
92142
  const timeoutId = setTimeout(() => globalController.abort(), timeoutMs);
92143
+ const clientDisconnected = () => res.destroyed && !res.writableEnded;
92144
+ const abortError = () => clientDisconnected() ? new ClientDisconnectedError() : new Error(`Request timed out after ${timeoutMs}ms`);
92131
92145
  const onClientClose = () => {
92132
- if (!globalController.signal.aborted) {
92146
+ if (!res.writableEnded && !globalController.signal.aborted) {
92133
92147
  console.log(`[ClawRouter] Client disconnected \u2014 aborting upstream request`);
92134
92148
  globalController.abort();
92135
92149
  }
92136
92150
  };
92137
- req.on("close", onClientClose);
92151
+ res.on("close", onClientClose);
92152
+ if (res.destroyed) onClientClose();
92138
92153
  try {
92139
92154
  let modelsToTry;
92140
92155
  const excludeList = options.excludeModels ?? loadExcludeList();
@@ -92193,7 +92208,7 @@ data: [DONE]
92193
92208
  completed = true;
92194
92209
  deduplicator.removeInflight(dedupKey);
92195
92210
  clearTimeout(timeoutId);
92196
- req.removeListener("close", onClientClose);
92211
+ res.removeListener("close", onClientClose);
92197
92212
  return;
92198
92213
  }
92199
92214
  const contextExcluded = fullChain.filter((m) => !contextFiltered.includes(m));
@@ -92292,7 +92307,7 @@ data: [DONE]
92292
92307
  }
92293
92308
  deduplicator.removeInflight(dedupKey);
92294
92309
  clearTimeout(timeoutId);
92295
- req.removeListener("close", onClientClose);
92310
+ res.removeListener("close", onClientClose);
92296
92311
  return;
92297
92312
  }
92298
92313
  if (excluded.length > 0) {
@@ -92323,7 +92338,7 @@ data: [DONE]
92323
92338
  const tryModel = modelsToTry[i];
92324
92339
  const isLastAttempt = i === modelsToTry.length - 1;
92325
92340
  if (globalController.signal.aborted) {
92326
- throw new Error(`Request timed out after ${timeoutMs}ms`);
92341
+ throw abortError();
92327
92342
  }
92328
92343
  console.log(`[ClawRouter] Trying model ${i + 1}/${modelsToTry.length}: ${tryModel}`);
92329
92344
  const perAttemptTimeoutMs = timeoutForModel(tryModel);
@@ -92343,7 +92358,7 @@ data: [DONE]
92343
92358
  );
92344
92359
  clearTimeout(modelTimeoutId);
92345
92360
  if (globalController.signal.aborted) {
92346
- throw new Error(`Request timed out after ${timeoutMs}ms`);
92361
+ throw abortError();
92347
92362
  }
92348
92363
  if (!result.success && modelController.signal.aborted && !isLastAttempt) {
92349
92364
  console.log(
@@ -92555,7 +92570,7 @@ data: [DONE]
92555
92570
  break;
92556
92571
  }
92557
92572
  clearTimeout(timeoutId);
92558
- req.removeListener("close", onClientClose);
92573
+ res.removeListener("close", onClientClose);
92559
92574
  if (heartbeatInterval) {
92560
92575
  clearInterval(heartbeatInterval);
92561
92576
  heartbeatInterval = void 0;
@@ -93058,12 +93073,16 @@ data: [DONE]
93058
93073
  completed = true;
93059
93074
  } catch (err) {
93060
93075
  clearTimeout(timeoutId);
93061
- req.removeListener("close", onClientClose);
93076
+ res.removeListener("close", onClientClose);
93062
93077
  if (heartbeatInterval) {
93063
93078
  clearInterval(heartbeatInterval);
93064
93079
  heartbeatInterval = void 0;
93065
93080
  }
93066
93081
  deduplicator.removeInflight(dedupKey);
93082
+ if (err instanceof ClientDisconnectedError || err instanceof Error && err.name === "AbortError" && clientDisconnected()) {
93083
+ console.log(`[ClawRouter] Request cancelled \u2014 client disconnected`);
93084
+ return;
93085
+ }
93067
93086
  balanceMonitor.invalidate();
93068
93087
  if (err instanceof Error && err.name === "AbortError") {
93069
93088
  throw new Error(`Request timed out after ${timeoutMs}ms`, { cause: err });
@@ -93119,7 +93138,7 @@ data: [DONE]
93119
93138
  });
93120
93139
  }
93121
93140
  }
93122
- 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, IMAGE_MODEL_IDS, IMAGE_MODEL_SIZES, IMAGE_MODEL_ALIASES, VIDEO_PRICING, PHONE_PRICING;
93141
+ 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, ClientDisconnectedError, 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, IMAGE_MODEL_IDS, IMAGE_MODEL_SIZES, IMAGE_MODEL_ALIASES, VIDEO_PRICING, PHONE_PRICING;
93123
93142
  var init_proxy = __esm({
93124
93143
  "src/proxy.ts"() {
93125
93144
  "use strict";
@@ -93199,6 +93218,12 @@ var init_proxy = __esm({
93199
93218
  PORT_RETRY_DELAY_MS = 1e3;
93200
93219
  MODEL_BODY_READ_TIMEOUT_MS = 3e5;
93201
93220
  ERROR_BODY_READ_TIMEOUT_MS = 3e4;
93221
+ ClientDisconnectedError = class extends Error {
93222
+ constructor() {
93223
+ super("Client disconnected");
93224
+ this.name = "ClientDisconnectedError";
93225
+ }
93226
+ };
93202
93227
  rateLimitedModels = /* @__PURE__ */ new Map();
93203
93228
  overloadedModels = /* @__PURE__ */ new Map();
93204
93229
  perProviderErrors = /* @__PURE__ */ new Map();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/clawrouter",
3
- "version": "0.12.252",
3
+ "version": "0.12.254",
4
4
  "description": "Smart LLM router — save 88% on inference costs. 71 models (5 free), one wallet, x402 micropayments.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",