@blockrun/llm 3.20.0 → 3.20.1

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
@@ -318,13 +318,19 @@ a retry disposition, which `retryDisposition(err)` returns:
318
318
 
319
319
  - `'unpaid'`: nothing chargeable was sent — the unpaid first request and its
320
320
  402 challenge, or signing the payment. A 429, 5xx, timeout or network error
321
- here moves on to the next model.
321
+ here moves on to the next model. On Solana, a `503
322
+ PAYMENT_VERIFICATION_UNAVAILABLE` in answer to the payment is `'unpaid'`
323
+ too: the gateway sends it only when verification could not run, so nothing
324
+ was settled or broadcast (the batch path already treats it as a refusal).
325
+ This holds on every exact-paid Solana endpoint, not only chat.
322
326
  - `'paid-or-in-doubt'`: the signed payment (exact or batch) was sent and may
323
327
  have been charged — a timeout, abort or network error after sending it, any
324
328
  error status in answer to it, or a 2xx whose body could not be read. The
325
329
  error propagates; no other model is bought for the call. With an API key
326
- the request itself is billed, so only the account API's explicit 4xx
327
- answer (such as a 429) is `'unpaid'`; a 5xx or a timeout is not.
330
+ the request itself is billed, so only the account API's explicit answers
331
+ are `'unpaid'`: a 4xx (such as a 429), or a 5xx carrying its JSON error
332
+ envelope (api.blockrun.ai debits only an accepted 2xx). An HTML or empty
333
+ 5xx from a proxy, or a timeout, is not.
328
334
 
329
335
  An error without a disposition counts as `'paid-or-in-doubt'`. Use the same
330
336
  check in your own retry wrapper:
package/dist/index.cjs CHANGED
@@ -332,7 +332,13 @@ function resolveApiKeyAuth(options) {
332
332
  return new ApiKeyAuth(key.trim(), base);
333
333
  }
334
334
  function accountErrorDisposition(err) {
335
- return err instanceof APIError && err.statusCode >= 400 && err.statusCode < 500 ? "unpaid" : "paid-or-in-doubt";
335
+ if (!(err instanceof APIError)) return "paid-or-in-doubt";
336
+ if (err.statusCode >= 400 && err.statusCode < 500) return "unpaid";
337
+ if (err.statusCode >= 500 && hasGatewayErrorEnvelope(err.response)) return "unpaid";
338
+ return "paid-or-in-doubt";
339
+ }
340
+ function hasGatewayErrorEnvelope(response) {
341
+ return !!response && typeof response === "object" && typeof response.message === "string" && response.message.length > 0;
336
342
  }
337
343
  function requireWallet(value) {
338
344
  if (value === void 0) throw new Error("This operation requires a wallet; the client uses API key account billing.");
@@ -4684,7 +4690,7 @@ function getCostSummary() {
4684
4690
  }
4685
4691
 
4686
4692
  // src/version.ts
4687
- var SDK_VERSION = "3.20.0";
4693
+ var SDK_VERSION = "3.20.1";
4688
4694
  var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
4689
4695
 
4690
4696
  // src/client.ts
@@ -11532,7 +11538,7 @@ var SolanaBatchPayer = class {
11532
11538
  cause: await afterPaymentError(response)
11533
11539
  };
11534
11540
  }
11535
- return { kind: "not_charged", reason: "payment_required", status: status2, depositSafe: false };
11541
+ return { kind: "not_charged", reason: "payment_required", status: status2, errorReason: receipt?.errorReason, depositSafe: provesNothingBroadcast(receipt) };
11536
11542
  }
11537
11543
  const refusal = await batchRefusal(response);
11538
11544
  if (refusal) {
@@ -12911,9 +12917,10 @@ var SolanaLLMClient = class {
12911
12917
  } catch {
12912
12918
  errorBody = { error: "Request failed" };
12913
12919
  }
12920
+ const unverified = response.status === 503 && errorBody?.code === "PAYMENT_VERIFICATION_UNAVAILABLE";
12914
12921
  throw withDisposition(
12915
12922
  new APIError(`API error after payment: ${response.status}`, response.status, sanitizeErrorResponse(errorBody)),
12916
- "paid-or-in-doubt"
12923
+ unverified ? "unpaid" : "paid-or-in-doubt"
12917
12924
  );
12918
12925
  }
12919
12926
  }
@@ -13385,8 +13392,12 @@ var AnthropicClient = class {
13385
13392
  baseURL: this._apiUrl,
13386
13393
  apiKey: "blockrun",
13387
13394
  fetch: this._x402Fetch.bind(this),
13388
- // Account POSTs may already be billed when an upstream error arrives.
13389
- ...this.apiAuth ? { maxRetries: 0 } : {}
13395
+ // Never let the Anthropic SDK retry. It retries 408/409/429/5xx and
13396
+ // connection errors by calling this fetch again, which in wallet mode
13397
+ // runs the whole x402 flow and signs a NEW payment each time (three
13398
+ // payments for one call at the default maxRetries of 2); in account
13399
+ // mode the POST itself may already be billed.
13400
+ maxRetries: 0
13390
13401
  });
13391
13402
  return this._client;
13392
13403
  })();
package/dist/index.js CHANGED
@@ -206,7 +206,13 @@ function resolveApiKeyAuth(options) {
206
206
  return new ApiKeyAuth(key.trim(), base);
207
207
  }
208
208
  function accountErrorDisposition(err) {
209
- return err instanceof APIError && err.statusCode >= 400 && err.statusCode < 500 ? "unpaid" : "paid-or-in-doubt";
209
+ if (!(err instanceof APIError)) return "paid-or-in-doubt";
210
+ if (err.statusCode >= 400 && err.statusCode < 500) return "unpaid";
211
+ if (err.statusCode >= 500 && hasGatewayErrorEnvelope(err.response)) return "unpaid";
212
+ return "paid-or-in-doubt";
213
+ }
214
+ function hasGatewayErrorEnvelope(response) {
215
+ return !!response && typeof response === "object" && typeof response.message === "string" && response.message.length > 0;
210
216
  }
211
217
  function requireWallet(value) {
212
218
  if (value === void 0) throw new Error("This operation requires a wallet; the client uses API key account billing.");
@@ -4558,7 +4564,7 @@ function getCostSummary() {
4558
4564
  }
4559
4565
 
4560
4566
  // src/version.ts
4561
- var SDK_VERSION = "3.20.0";
4567
+ var SDK_VERSION = "3.20.1";
4562
4568
  var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
4563
4569
 
4564
4570
  // src/client.ts
@@ -11406,7 +11412,7 @@ var SolanaBatchPayer = class {
11406
11412
  cause: await afterPaymentError(response)
11407
11413
  };
11408
11414
  }
11409
- return { kind: "not_charged", reason: "payment_required", status: status2, depositSafe: false };
11415
+ return { kind: "not_charged", reason: "payment_required", status: status2, errorReason: receipt?.errorReason, depositSafe: provesNothingBroadcast(receipt) };
11410
11416
  }
11411
11417
  const refusal = await batchRefusal(response);
11412
11418
  if (refusal) {
@@ -12785,9 +12791,10 @@ var SolanaLLMClient = class {
12785
12791
  } catch {
12786
12792
  errorBody = { error: "Request failed" };
12787
12793
  }
12794
+ const unverified = response.status === 503 && errorBody?.code === "PAYMENT_VERIFICATION_UNAVAILABLE";
12788
12795
  throw withDisposition(
12789
12796
  new APIError(`API error after payment: ${response.status}`, response.status, sanitizeErrorResponse(errorBody)),
12790
- "paid-or-in-doubt"
12797
+ unverified ? "unpaid" : "paid-or-in-doubt"
12791
12798
  );
12792
12799
  }
12793
12800
  }
@@ -13259,8 +13266,12 @@ var AnthropicClient = class {
13259
13266
  baseURL: this._apiUrl,
13260
13267
  apiKey: "blockrun",
13261
13268
  fetch: this._x402Fetch.bind(this),
13262
- // Account POSTs may already be billed when an upstream error arrives.
13263
- ...this.apiAuth ? { maxRetries: 0 } : {}
13269
+ // Never let the Anthropic SDK retry. It retries 408/409/429/5xx and
13270
+ // connection errors by calling this fetch again, which in wallet mode
13271
+ // runs the whole x402 flow and signs a NEW payment each time (three
13272
+ // payments for one call at the default maxRetries of 2); in account
13273
+ // mode the POST itself may already be billed.
13274
+ maxRetries: 0
13264
13275
  });
13265
13276
  return this._client;
13266
13277
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/llm",
3
- "version": "3.20.0",
3
+ "version": "3.20.1",
4
4
  "type": "module",
5
5
  "description": "TypeScript SDK for BlockRun - every frontier model behind one OpenAI-compatible client. Pay with a BlockRun API key or per-call in USDC. Smart routing picks the cheapest capable model. No rate limits.",
6
6
  "main": "dist/index.cjs",