@blockrun/clawrouter 0.8.11 → 0.8.12

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/cli.js CHANGED
@@ -2223,6 +2223,42 @@ var HEALTH_CHECK_TIMEOUT_MS = 2e3;
2223
2223
  var RATE_LIMIT_COOLDOWN_MS = 6e4;
2224
2224
  var PORT_RETRY_ATTEMPTS = 5;
2225
2225
  var PORT_RETRY_DELAY_MS = 1e3;
2226
+ function transformPaymentError(errorBody) {
2227
+ try {
2228
+ const parsed = JSON.parse(errorBody);
2229
+ if (parsed.error === "Payment verification failed" && parsed.details) {
2230
+ const match = parsed.details.match(/Verification failed:\s*(\{.*\})/s);
2231
+ if (match) {
2232
+ const innerJson = JSON.parse(match[1]);
2233
+ if (innerJson.invalidReason === "insufficient_funds" && innerJson.invalidMessage) {
2234
+ const balanceMatch = innerJson.invalidMessage.match(
2235
+ /insufficient balance:\s*(\d+)\s*<\s*(\d+)/i
2236
+ );
2237
+ if (balanceMatch) {
2238
+ const currentMicros = parseInt(balanceMatch[1], 10);
2239
+ const requiredMicros = parseInt(balanceMatch[2], 10);
2240
+ const currentUSD = (currentMicros / 1e6).toFixed(6);
2241
+ const requiredUSD = (requiredMicros / 1e6).toFixed(6);
2242
+ const wallet = innerJson.payer || "unknown";
2243
+ const shortWallet = wallet.length > 12 ? `${wallet.slice(0, 6)}...${wallet.slice(-4)}` : wallet;
2244
+ return JSON.stringify({
2245
+ error: {
2246
+ message: `Insufficient USDC balance. Current: $${currentUSD}, Required: ~$${requiredUSD}`,
2247
+ type: "insufficient_funds",
2248
+ wallet,
2249
+ current_balance_usd: currentUSD,
2250
+ required_usd: requiredUSD,
2251
+ help: `Fund wallet ${shortWallet} with USDC on Base, or use free model: /model free`
2252
+ }
2253
+ });
2254
+ }
2255
+ }
2256
+ }
2257
+ }
2258
+ } catch {
2259
+ }
2260
+ return errorBody;
2261
+ }
2226
2262
  var rateLimitedModels = /* @__PURE__ */ new Map();
2227
2263
  function isRateLimited(modelId) {
2228
2264
  const hitTime = rateLimitedModels.get(modelId);
@@ -3091,10 +3127,18 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
3091
3127
  options.onRouted?.(routingDecision);
3092
3128
  }
3093
3129
  if (!upstream) {
3094
- const errBody = lastError?.body || "All models in fallback chain failed";
3130
+ const rawErrBody = lastError?.body || "All models in fallback chain failed";
3095
3131
  const errStatus = lastError?.status || 502;
3132
+ const transformedErr = transformPaymentError(rawErrBody);
3096
3133
  if (headersSentEarly) {
3097
- const errEvent = `data: ${JSON.stringify({ error: { message: errBody, type: "provider_error", status: errStatus } })}
3134
+ let errPayload;
3135
+ try {
3136
+ const parsed = JSON.parse(transformedErr);
3137
+ errPayload = JSON.stringify(parsed);
3138
+ } catch {
3139
+ errPayload = JSON.stringify({ error: { message: rawErrBody, type: "provider_error", status: errStatus } });
3140
+ }
3141
+ const errEvent = `data: ${errPayload}
3098
3142
 
3099
3143
  `;
3100
3144
  safeWrite(res, errEvent);
@@ -3109,17 +3153,11 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
3109
3153
  });
3110
3154
  } else {
3111
3155
  res.writeHead(errStatus, { "Content-Type": "application/json" });
3112
- res.end(
3113
- JSON.stringify({
3114
- error: { message: errBody, type: "provider_error" }
3115
- })
3116
- );
3156
+ res.end(transformedErr);
3117
3157
  deduplicator.complete(dedupKey, {
3118
3158
  status: errStatus,
3119
3159
  headers: { "content-type": "application/json" },
3120
- body: Buffer.from(
3121
- JSON.stringify({ error: { message: errBody, type: "provider_error" } })
3122
- ),
3160
+ body: Buffer.from(transformedErr),
3123
3161
  completedAt: Date.now()
3124
3162
  });
3125
3163
  }