@blockrun/clawrouter 0.12.253 → 0.12.255

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 +31 -16
  2. package/dist/index.js +31 -16
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -90441,7 +90441,7 @@ async function startProxy(options) {
90441
90441
  console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
90442
90442
  } else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
90443
90443
  try {
90444
- const imgResp = await fetch(img.url);
90444
+ const imgResp = await fetch(img.url, { signal: clientAbort.signal });
90445
90445
  if (imgResp.ok) {
90446
90446
  const contentType = imgResp.headers.get("content-type") ?? "image/png";
90447
90447
  const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
@@ -90523,6 +90523,7 @@ async function startProxy(options) {
90523
90523
  img2imgCost = estimateImageCost(img2imgModel, parsed.size, parsed.n || 1);
90524
90524
  reqBody = JSON.stringify(parsed);
90525
90525
  } catch (parseErr) {
90526
+ if (clientAbort.signal.aborted) return;
90526
90527
  const msg = parseErr instanceof Error ? parseErr.message : String(parseErr);
90527
90528
  res.writeHead(400, { "Content-Type": "application/json" });
90528
90529
  res.end(JSON.stringify({ error: "Invalid request", details: msg }));
@@ -90563,7 +90564,7 @@ async function startProxy(options) {
90563
90564
  console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
90564
90565
  } else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
90565
90566
  try {
90566
- const imgResp = await fetch(img.url);
90567
+ const imgResp = await fetch(img.url, { signal: clientAbort.signal });
90567
90568
  if (imgResp.ok) {
90568
90569
  const contentType = imgResp.headers.get("content-type") ?? "image/png";
90569
90570
  const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
@@ -90809,7 +90810,7 @@ async function startProxy(options) {
90809
90810
  for (const clip of finalResult.data) {
90810
90811
  if (clip.url?.startsWith("https://") || clip.url?.startsWith("http://")) {
90811
90812
  try {
90812
- const videoResp = await fetch(clip.url);
90813
+ const videoResp = await fetch(clip.url, { signal: clientAbort.signal });
90813
90814
  if (videoResp.ok) {
90814
90815
  const contentType = videoResp.headers.get("content-type") ?? "video/mp4";
90815
90816
  const ext = contentType.includes("webm") ? "webm" : contentType.includes("quicktime") ? "mov" : "mp4";
@@ -91428,6 +91429,10 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91428
91429
  console.log(
91429
91430
  `[ClawRouter] /imagegen command \u2192 ${imageModel} (${imageSize}): ${imagePrompt.slice(0, 80)}...`
91430
91431
  );
91432
+ const imagegenAbort = new AbortController();
91433
+ res.on("close", () => {
91434
+ if (!res.writableEnded) imagegenAbort.abort();
91435
+ });
91431
91436
  try {
91432
91437
  const imageUpstreamUrl = `${apiBase}/v1/images/generations`;
91433
91438
  const imageBody = JSON.stringify({
@@ -91436,10 +91441,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91436
91441
  size: imageSize,
91437
91442
  n: 1
91438
91443
  });
91439
- const imagegenAbort = new AbortController();
91440
- res.on("close", () => {
91441
- if (!res.writableEnded) imagegenAbort.abort();
91442
- });
91443
91444
  const imageResponse = await payFetch(imageUpstreamUrl, {
91444
91445
  method: "POST",
91445
91446
  headers: { "content-type": "application/json", "user-agent": USER_AGENT },
@@ -91581,6 +91582,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91581
91582
  );
91582
91583
  }
91583
91584
  } catch (err) {
91585
+ if (imagegenAbort.signal.aborted) return;
91584
91586
  const errMsg = err instanceof Error ? err.message : String(err);
91585
91587
  console.error(`[ClawRouter] /imagegen error: ${errMsg}`);
91586
91588
  if (!res.headersSent) {
@@ -92320,13 +92322,16 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
92320
92322
  const timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
92321
92323
  const globalController = new AbortController();
92322
92324
  const timeoutId = setTimeout(() => globalController.abort(), timeoutMs);
92325
+ const clientDisconnected = () => res.destroyed && !res.writableEnded;
92326
+ const abortError = () => clientDisconnected() ? new ClientDisconnectedError() : new Error(`Request timed out after ${timeoutMs}ms`);
92323
92327
  const onClientClose = () => {
92324
- if (!globalController.signal.aborted) {
92328
+ if (!res.writableEnded && !globalController.signal.aborted) {
92325
92329
  console.log(`[ClawRouter] Client disconnected \u2014 aborting upstream request`);
92326
92330
  globalController.abort();
92327
92331
  }
92328
92332
  };
92329
- req.on("close", onClientClose);
92333
+ res.on("close", onClientClose);
92334
+ if (res.destroyed) onClientClose();
92330
92335
  try {
92331
92336
  let modelsToTry;
92332
92337
  const excludeList = options.excludeModels ?? loadExcludeList();
@@ -92385,7 +92390,7 @@ data: [DONE]
92385
92390
  completed = true;
92386
92391
  deduplicator.removeInflight(dedupKey);
92387
92392
  clearTimeout(timeoutId);
92388
- req.removeListener("close", onClientClose);
92393
+ res.removeListener("close", onClientClose);
92389
92394
  return;
92390
92395
  }
92391
92396
  const contextExcluded = fullChain.filter((m) => !contextFiltered.includes(m));
@@ -92484,7 +92489,7 @@ data: [DONE]
92484
92489
  }
92485
92490
  deduplicator.removeInflight(dedupKey);
92486
92491
  clearTimeout(timeoutId);
92487
- req.removeListener("close", onClientClose);
92492
+ res.removeListener("close", onClientClose);
92488
92493
  return;
92489
92494
  }
92490
92495
  if (excluded.length > 0) {
@@ -92515,7 +92520,7 @@ data: [DONE]
92515
92520
  const tryModel = modelsToTry[i];
92516
92521
  const isLastAttempt = i === modelsToTry.length - 1;
92517
92522
  if (globalController.signal.aborted) {
92518
- throw new Error(`Request timed out after ${timeoutMs}ms`);
92523
+ throw abortError();
92519
92524
  }
92520
92525
  console.log(`[ClawRouter] Trying model ${i + 1}/${modelsToTry.length}: ${tryModel}`);
92521
92526
  const perAttemptTimeoutMs = timeoutForModel(tryModel);
@@ -92535,7 +92540,7 @@ data: [DONE]
92535
92540
  );
92536
92541
  clearTimeout(modelTimeoutId);
92537
92542
  if (globalController.signal.aborted) {
92538
- throw new Error(`Request timed out after ${timeoutMs}ms`);
92543
+ throw abortError();
92539
92544
  }
92540
92545
  if (!result.success && modelController.signal.aborted && !isLastAttempt) {
92541
92546
  console.log(
@@ -92747,7 +92752,7 @@ data: [DONE]
92747
92752
  break;
92748
92753
  }
92749
92754
  clearTimeout(timeoutId);
92750
- req.removeListener("close", onClientClose);
92755
+ res.removeListener("close", onClientClose);
92751
92756
  if (heartbeatInterval) {
92752
92757
  clearInterval(heartbeatInterval);
92753
92758
  heartbeatInterval = void 0;
@@ -93250,12 +93255,16 @@ data: [DONE]
93250
93255
  completed = true;
93251
93256
  } catch (err) {
93252
93257
  clearTimeout(timeoutId);
93253
- req.removeListener("close", onClientClose);
93258
+ res.removeListener("close", onClientClose);
93254
93259
  if (heartbeatInterval) {
93255
93260
  clearInterval(heartbeatInterval);
93256
93261
  heartbeatInterval = void 0;
93257
93262
  }
93258
93263
  deduplicator.removeInflight(dedupKey);
93264
+ if (err instanceof ClientDisconnectedError || err instanceof Error && err.name === "AbortError" && clientDisconnected()) {
93265
+ console.log(`[ClawRouter] Request cancelled \u2014 client disconnected`);
93266
+ return;
93267
+ }
93259
93268
  balanceMonitor.invalidate();
93260
93269
  if (err instanceof Error && err.name === "AbortError") {
93261
93270
  throw new Error(`Request timed out after ${timeoutMs}ms`, { cause: err });
@@ -93311,7 +93320,7 @@ data: [DONE]
93311
93320
  });
93312
93321
  }
93313
93322
  }
93314
- 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;
93323
+ 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;
93315
93324
  var init_proxy = __esm({
93316
93325
  "src/proxy.ts"() {
93317
93326
  "use strict";
@@ -93391,6 +93400,12 @@ var init_proxy = __esm({
93391
93400
  PORT_RETRY_DELAY_MS = 1e3;
93392
93401
  MODEL_BODY_READ_TIMEOUT_MS = 3e5;
93393
93402
  ERROR_BODY_READ_TIMEOUT_MS = 3e4;
93403
+ ClientDisconnectedError = class extends Error {
93404
+ constructor() {
93405
+ super("Client disconnected");
93406
+ this.name = "ClientDisconnectedError";
93407
+ }
93408
+ };
93394
93409
  rateLimitedModels = /* @__PURE__ */ new Map();
93395
93410
  overloadedModels = /* @__PURE__ */ new Map();
93396
93411
  perProviderErrors = /* @__PURE__ */ new Map();
package/dist/index.js CHANGED
@@ -90261,7 +90261,7 @@ async function startProxy(options) {
90261
90261
  console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
90262
90262
  } else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
90263
90263
  try {
90264
- const imgResp = await fetch(img.url);
90264
+ const imgResp = await fetch(img.url, { signal: clientAbort.signal });
90265
90265
  if (imgResp.ok) {
90266
90266
  const contentType = imgResp.headers.get("content-type") ?? "image/png";
90267
90267
  const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
@@ -90343,6 +90343,7 @@ async function startProxy(options) {
90343
90343
  img2imgCost = estimateImageCost(img2imgModel, parsed.size, parsed.n || 1);
90344
90344
  reqBody = JSON.stringify(parsed);
90345
90345
  } catch (parseErr) {
90346
+ if (clientAbort.signal.aborted) return;
90346
90347
  const msg = parseErr instanceof Error ? parseErr.message : String(parseErr);
90347
90348
  res.writeHead(400, { "Content-Type": "application/json" });
90348
90349
  res.end(JSON.stringify({ error: "Invalid request", details: msg }));
@@ -90383,7 +90384,7 @@ async function startProxy(options) {
90383
90384
  console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
90384
90385
  } else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
90385
90386
  try {
90386
- const imgResp = await fetch(img.url);
90387
+ const imgResp = await fetch(img.url, { signal: clientAbort.signal });
90387
90388
  if (imgResp.ok) {
90388
90389
  const contentType = imgResp.headers.get("content-type") ?? "image/png";
90389
90390
  const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
@@ -90629,7 +90630,7 @@ async function startProxy(options) {
90629
90630
  for (const clip of finalResult.data) {
90630
90631
  if (clip.url?.startsWith("https://") || clip.url?.startsWith("http://")) {
90631
90632
  try {
90632
- const videoResp = await fetch(clip.url);
90633
+ const videoResp = await fetch(clip.url, { signal: clientAbort.signal });
90633
90634
  if (videoResp.ok) {
90634
90635
  const contentType = videoResp.headers.get("content-type") ?? "video/mp4";
90635
90636
  const ext = contentType.includes("webm") ? "webm" : contentType.includes("quicktime") ? "mov" : "mp4";
@@ -91248,6 +91249,10 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91248
91249
  console.log(
91249
91250
  `[ClawRouter] /imagegen command \u2192 ${imageModel} (${imageSize}): ${imagePrompt.slice(0, 80)}...`
91250
91251
  );
91252
+ const imagegenAbort = new AbortController();
91253
+ res.on("close", () => {
91254
+ if (!res.writableEnded) imagegenAbort.abort();
91255
+ });
91251
91256
  try {
91252
91257
  const imageUpstreamUrl = `${apiBase}/v1/images/generations`;
91253
91258
  const imageBody = JSON.stringify({
@@ -91256,10 +91261,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91256
91261
  size: imageSize,
91257
91262
  n: 1
91258
91263
  });
91259
- const imagegenAbort = new AbortController();
91260
- res.on("close", () => {
91261
- if (!res.writableEnded) imagegenAbort.abort();
91262
- });
91263
91264
  const imageResponse = await payFetch(imageUpstreamUrl, {
91264
91265
  method: "POST",
91265
91266
  headers: { "content-type": "application/json", "user-agent": USER_AGENT },
@@ -91401,6 +91402,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
91401
91402
  );
91402
91403
  }
91403
91404
  } catch (err) {
91405
+ if (imagegenAbort.signal.aborted) return;
91404
91406
  const errMsg = err instanceof Error ? err.message : String(err);
91405
91407
  console.error(`[ClawRouter] /imagegen error: ${errMsg}`);
91406
91408
  if (!res.headersSent) {
@@ -92140,13 +92142,16 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
92140
92142
  const timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
92141
92143
  const globalController = new AbortController();
92142
92144
  const timeoutId = setTimeout(() => globalController.abort(), timeoutMs);
92145
+ const clientDisconnected = () => res.destroyed && !res.writableEnded;
92146
+ const abortError = () => clientDisconnected() ? new ClientDisconnectedError() : new Error(`Request timed out after ${timeoutMs}ms`);
92143
92147
  const onClientClose = () => {
92144
- if (!globalController.signal.aborted) {
92148
+ if (!res.writableEnded && !globalController.signal.aborted) {
92145
92149
  console.log(`[ClawRouter] Client disconnected \u2014 aborting upstream request`);
92146
92150
  globalController.abort();
92147
92151
  }
92148
92152
  };
92149
- req.on("close", onClientClose);
92153
+ res.on("close", onClientClose);
92154
+ if (res.destroyed) onClientClose();
92150
92155
  try {
92151
92156
  let modelsToTry;
92152
92157
  const excludeList = options.excludeModels ?? loadExcludeList();
@@ -92205,7 +92210,7 @@ data: [DONE]
92205
92210
  completed = true;
92206
92211
  deduplicator.removeInflight(dedupKey);
92207
92212
  clearTimeout(timeoutId);
92208
- req.removeListener("close", onClientClose);
92213
+ res.removeListener("close", onClientClose);
92209
92214
  return;
92210
92215
  }
92211
92216
  const contextExcluded = fullChain.filter((m) => !contextFiltered.includes(m));
@@ -92304,7 +92309,7 @@ data: [DONE]
92304
92309
  }
92305
92310
  deduplicator.removeInflight(dedupKey);
92306
92311
  clearTimeout(timeoutId);
92307
- req.removeListener("close", onClientClose);
92312
+ res.removeListener("close", onClientClose);
92308
92313
  return;
92309
92314
  }
92310
92315
  if (excluded.length > 0) {
@@ -92335,7 +92340,7 @@ data: [DONE]
92335
92340
  const tryModel = modelsToTry[i];
92336
92341
  const isLastAttempt = i === modelsToTry.length - 1;
92337
92342
  if (globalController.signal.aborted) {
92338
- throw new Error(`Request timed out after ${timeoutMs}ms`);
92343
+ throw abortError();
92339
92344
  }
92340
92345
  console.log(`[ClawRouter] Trying model ${i + 1}/${modelsToTry.length}: ${tryModel}`);
92341
92346
  const perAttemptTimeoutMs = timeoutForModel(tryModel);
@@ -92355,7 +92360,7 @@ data: [DONE]
92355
92360
  );
92356
92361
  clearTimeout(modelTimeoutId);
92357
92362
  if (globalController.signal.aborted) {
92358
- throw new Error(`Request timed out after ${timeoutMs}ms`);
92363
+ throw abortError();
92359
92364
  }
92360
92365
  if (!result.success && modelController.signal.aborted && !isLastAttempt) {
92361
92366
  console.log(
@@ -92567,7 +92572,7 @@ data: [DONE]
92567
92572
  break;
92568
92573
  }
92569
92574
  clearTimeout(timeoutId);
92570
- req.removeListener("close", onClientClose);
92575
+ res.removeListener("close", onClientClose);
92571
92576
  if (heartbeatInterval) {
92572
92577
  clearInterval(heartbeatInterval);
92573
92578
  heartbeatInterval = void 0;
@@ -93070,12 +93075,16 @@ data: [DONE]
93070
93075
  completed = true;
93071
93076
  } catch (err) {
93072
93077
  clearTimeout(timeoutId);
93073
- req.removeListener("close", onClientClose);
93078
+ res.removeListener("close", onClientClose);
93074
93079
  if (heartbeatInterval) {
93075
93080
  clearInterval(heartbeatInterval);
93076
93081
  heartbeatInterval = void 0;
93077
93082
  }
93078
93083
  deduplicator.removeInflight(dedupKey);
93084
+ if (err instanceof ClientDisconnectedError || err instanceof Error && err.name === "AbortError" && clientDisconnected()) {
93085
+ console.log(`[ClawRouter] Request cancelled \u2014 client disconnected`);
93086
+ return;
93087
+ }
93079
93088
  balanceMonitor.invalidate();
93080
93089
  if (err instanceof Error && err.name === "AbortError") {
93081
93090
  throw new Error(`Request timed out after ${timeoutMs}ms`, { cause: err });
@@ -93131,7 +93140,7 @@ data: [DONE]
93131
93140
  });
93132
93141
  }
93133
93142
  }
93134
- 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;
93143
+ 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;
93135
93144
  var init_proxy = __esm({
93136
93145
  "src/proxy.ts"() {
93137
93146
  "use strict";
@@ -93211,6 +93220,12 @@ var init_proxy = __esm({
93211
93220
  PORT_RETRY_DELAY_MS = 1e3;
93212
93221
  MODEL_BODY_READ_TIMEOUT_MS = 3e5;
93213
93222
  ERROR_BODY_READ_TIMEOUT_MS = 3e4;
93223
+ ClientDisconnectedError = class extends Error {
93224
+ constructor() {
93225
+ super("Client disconnected");
93226
+ this.name = "ClientDisconnectedError";
93227
+ }
93228
+ };
93214
93229
  rateLimitedModels = /* @__PURE__ */ new Map();
93215
93230
  overloadedModels = /* @__PURE__ */ new Map();
93216
93231
  perProviderErrors = /* @__PURE__ */ new Map();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/clawrouter",
3
- "version": "0.12.253",
3
+ "version": "0.12.255",
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",