@blockrun/clawrouter 0.8.11 → 0.8.13

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/dist/index.js CHANGED
@@ -2362,6 +2362,42 @@ var HEALTH_CHECK_TIMEOUT_MS = 2e3;
2362
2362
  var RATE_LIMIT_COOLDOWN_MS = 6e4;
2363
2363
  var PORT_RETRY_ATTEMPTS = 5;
2364
2364
  var PORT_RETRY_DELAY_MS = 1e3;
2365
+ function transformPaymentError(errorBody) {
2366
+ try {
2367
+ const parsed = JSON.parse(errorBody);
2368
+ if (parsed.error === "Payment verification failed" && parsed.details) {
2369
+ const match = parsed.details.match(/Verification failed:\s*(\{.*\})/s);
2370
+ if (match) {
2371
+ const innerJson = JSON.parse(match[1]);
2372
+ if (innerJson.invalidReason === "insufficient_funds" && innerJson.invalidMessage) {
2373
+ const balanceMatch = innerJson.invalidMessage.match(
2374
+ /insufficient balance:\s*(\d+)\s*<\s*(\d+)/i
2375
+ );
2376
+ if (balanceMatch) {
2377
+ const currentMicros = parseInt(balanceMatch[1], 10);
2378
+ const requiredMicros = parseInt(balanceMatch[2], 10);
2379
+ const currentUSD = (currentMicros / 1e6).toFixed(6);
2380
+ const requiredUSD = (requiredMicros / 1e6).toFixed(6);
2381
+ const wallet = innerJson.payer || "unknown";
2382
+ const shortWallet = wallet.length > 12 ? `${wallet.slice(0, 6)}...${wallet.slice(-4)}` : wallet;
2383
+ return JSON.stringify({
2384
+ error: {
2385
+ message: `Insufficient USDC balance. Current: $${currentUSD}, Required: ~$${requiredUSD}`,
2386
+ type: "insufficient_funds",
2387
+ wallet,
2388
+ current_balance_usd: currentUSD,
2389
+ required_usd: requiredUSD,
2390
+ help: `Fund wallet ${shortWallet} with USDC on Base, or use free model: /model free`
2391
+ }
2392
+ });
2393
+ }
2394
+ }
2395
+ }
2396
+ }
2397
+ } catch {
2398
+ }
2399
+ return errorBody;
2400
+ }
2365
2401
  var rateLimitedModels = /* @__PURE__ */ new Map();
2366
2402
  function isRateLimited(modelId) {
2367
2403
  const hitTime = rateLimitedModels.get(modelId);
@@ -2606,12 +2642,16 @@ function normalizeMessagesForThinking(messages) {
2606
2642
  }
2607
2643
  var KIMI_BLOCK_RE = /<[||][^<>]*begin[^<>]*[||]>[\s\S]*?<[||][^<>]*end[^<>]*[||]>/gi;
2608
2644
  var KIMI_TOKEN_RE = /<[||][^<>]*[||]>/g;
2645
+ var DSML_BLOCK_RE = /<[||]DSML[||][^>]*>[\s\S]*?<\/[||]DSML[||][^>]*>/gi;
2646
+ var DSML_TAG_RE = /<\/?[||]DSML[||][^>]*>/gi;
2609
2647
  var THINKING_TAG_RE = /<\s*\/?\s*(?:think(?:ing)?|thought|antthinking)\b[^>]*>/gi;
2610
2648
  var THINKING_BLOCK_RE = /<\s*(?:think(?:ing)?|thought|antthinking)\b[^>]*>[\s\S]*?<\s*\/\s*(?:think(?:ing)?|thought|antthinking)\s*>/gi;
2611
2649
  function stripThinkingTokens(content) {
2612
2650
  if (!content) return content;
2613
2651
  let cleaned = content.replace(KIMI_BLOCK_RE, "");
2614
2652
  cleaned = cleaned.replace(KIMI_TOKEN_RE, "");
2653
+ cleaned = cleaned.replace(DSML_BLOCK_RE, "");
2654
+ cleaned = cleaned.replace(DSML_TAG_RE, "");
2615
2655
  cleaned = cleaned.replace(THINKING_BLOCK_RE, "");
2616
2656
  cleaned = cleaned.replace(THINKING_TAG_RE, "");
2617
2657
  return cleaned;
@@ -3230,10 +3270,18 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
3230
3270
  options.onRouted?.(routingDecision);
3231
3271
  }
3232
3272
  if (!upstream) {
3233
- const errBody = lastError?.body || "All models in fallback chain failed";
3273
+ const rawErrBody = lastError?.body || "All models in fallback chain failed";
3234
3274
  const errStatus = lastError?.status || 502;
3275
+ const transformedErr = transformPaymentError(rawErrBody);
3235
3276
  if (headersSentEarly) {
3236
- const errEvent = `data: ${JSON.stringify({ error: { message: errBody, type: "provider_error", status: errStatus } })}
3277
+ let errPayload;
3278
+ try {
3279
+ const parsed = JSON.parse(transformedErr);
3280
+ errPayload = JSON.stringify(parsed);
3281
+ } catch {
3282
+ errPayload = JSON.stringify({ error: { message: rawErrBody, type: "provider_error", status: errStatus } });
3283
+ }
3284
+ const errEvent = `data: ${errPayload}
3237
3285
 
3238
3286
  `;
3239
3287
  safeWrite(res, errEvent);
@@ -3248,17 +3296,11 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
3248
3296
  });
3249
3297
  } else {
3250
3298
  res.writeHead(errStatus, { "Content-Type": "application/json" });
3251
- res.end(
3252
- JSON.stringify({
3253
- error: { message: errBody, type: "provider_error" }
3254
- })
3255
- );
3299
+ res.end(transformedErr);
3256
3300
  deduplicator.complete(dedupKey, {
3257
3301
  status: errStatus,
3258
3302
  headers: { "content-type": "application/json" },
3259
- body: Buffer.from(
3260
- JSON.stringify({ error: { message: errBody, type: "provider_error" } })
3261
- ),
3303
+ body: Buffer.from(transformedErr),
3262
3304
  completedAt: Date.now()
3263
3305
  });
3264
3306
  }