@blockrun/llm 3.22.0 → 3.22.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
@@ -507,6 +507,9 @@ console.log(res.costUsd, res.settlement); // what you paid, and the tx
507
507
  (Base / Arc). `costUsd` is what the call added to `getSpending()`: the signed
508
508
  price under `exact`, the metered `extra.chargedAmount` under batch settlement,
509
509
  `0` for a free model; it is undefined in API-key mode (billed to the account).
510
+ When the gateway answers a paid request from a free fallback model it skips
511
+ settlement: `costUsd` is `0`, `settlement.skipped` is `"free-fallback"`, and
512
+ nothing is added to `getSpending()`.
510
513
 
511
514
  **Setup:**
512
515
  1. Export your Solana wallet key: `export SOLANA_WALLET_KEY="your-bs58-key"`
package/dist/index.cjs CHANGED
@@ -553,7 +553,15 @@ function readSettlement(response, quotedUsd, scheme) {
553
553
  };
554
554
  return { costUsd, settlement };
555
555
  }
556
+ function settlementSkipped(response) {
557
+ return response.headers.get("X-Settlement-Skipped") === "free-fallback";
558
+ }
556
559
  function withCost(body, response, bookedUsd, scheme) {
560
+ if (settlementSkipped(response)) {
561
+ body.costUsd = 0;
562
+ body.settlement = { ...readSettlement(response, bookedUsd, scheme).settlement, skipped: "free-fallback" };
563
+ return body;
564
+ }
557
565
  body.costUsd = bookedUsd;
558
566
  body.settlement = readSettlement(response, bookedUsd, scheme).settlement;
559
567
  return body;
@@ -4824,7 +4832,7 @@ function getCostSummary() {
4824
4832
  }
4825
4833
 
4826
4834
  // src/version.ts
4827
- var SDK_VERSION = "3.22.0";
4835
+ var SDK_VERSION = "3.22.1";
4828
4836
  var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
4829
4837
 
4830
4838
  // src/client.ts
@@ -5390,11 +5398,7 @@ var LLMClient = class _LLMClient {
5390
5398
  }
5391
5399
  throw new APIError(`API error after payment: ${retryResp2.status}`, retryResp2.status, sanitizeErrorResponse(errorBody));
5392
5400
  }
5393
- const costUsd2 = parseFloat(details.amount) / 1e6;
5394
- this.sessionCalls += 1;
5395
- this.sessionTotalUsd += costUsd2;
5396
- this.recordCost(url, costUsd2, { body, network: details.network });
5397
- return withCost(await this.parseChatResponse(retryResp2), retryResp2, costUsd2, "exact");
5401
+ return this.bookPaid(url, body, details, retryResp2);
5398
5402
  }
5399
5403
  }
5400
5404
  if (retryResponse.status === 402) {
@@ -5413,11 +5417,22 @@ var LLMClient = class _LLMClient {
5413
5417
  sanitizeErrorResponse(errorBody)
5414
5418
  );
5415
5419
  }
5420
+ return this.bookPaid(url, body, details, retryResponse);
5421
+ }
5422
+ /**
5423
+ * Book a served, paid chat call and attach its cost. A response the gateway
5424
+ * served from a free fallback with settlement skipped
5425
+ * (`X-Settlement-Skipped: free-fallback`) moved nothing on chain, so it is
5426
+ * not added to `getSpending()` or the cost log, and reports `costUsd: 0`.
5427
+ */
5428
+ async bookPaid(url, body, details, response) {
5416
5429
  const costUsd = parseFloat(details.amount) / 1e6;
5417
- this.sessionCalls += 1;
5418
- this.sessionTotalUsd += costUsd;
5419
- this.recordCost(url, costUsd, { body, network: details.network });
5420
- return withCost(await this.parseChatResponse(retryResponse), retryResponse, costUsd, "exact");
5430
+ if (!settlementSkipped(response)) {
5431
+ this.sessionCalls += 1;
5432
+ this.sessionTotalUsd += costUsd;
5433
+ this.recordCost(url, costUsd, { body, network: details.network });
5434
+ }
5435
+ return withCost(await this.parseChatResponse(response), response, costUsd, "exact");
5421
5436
  }
5422
5437
  /**
5423
5438
  * Sign a payment header and return the PAYMENT-SIGNATURE value.
@@ -13404,7 +13419,7 @@ var SolanaLLMClient = class {
13404
13419
  throw withDisposition(error, "paid-or-in-doubt");
13405
13420
  }
13406
13421
  await this.assertPaid(retryResponse);
13407
- this.recordSettlement(costUsd);
13422
+ if (!settlementSkipped(retryResponse)) this.recordSettlement(costUsd);
13408
13423
  const paid = await this.readPaidJson(retryResponse);
13409
13424
  return withCost(paid, retryResponse, costUsd, "exact");
13410
13425
  }
package/dist/index.d.cts CHANGED
@@ -230,6 +230,13 @@ interface Settlement {
230
230
  network?: string;
231
231
  /** Present and false only when the gateway reported a failed settlement. */
232
232
  success?: false;
233
+ /**
234
+ * `"free-fallback"` when the gateway served a paid request from a free
235
+ * fallback model and skipped settlement (`X-Settlement-Skipped`): nothing
236
+ * moved on chain, so `costUsd` is 0 and nothing was added to `getSpending()`.
237
+ * `quotedUsd` still states what was signed.
238
+ */
239
+ skipped?: "free-fallback";
233
240
  }
234
241
  interface FunctionCall {
235
242
  name: string;
@@ -1479,6 +1486,13 @@ declare class LLMClient {
1479
1486
  private signFrom402;
1480
1487
  /** Send the signed payment and read the answer. The payment may settle from here on. */
1481
1488
  private sendPaid;
1489
+ /**
1490
+ * Book a served, paid chat call and attach its cost. A response the gateway
1491
+ * served from a free fallback with settlement skipped
1492
+ * (`X-Settlement-Skipped: free-fallback`) moved nothing on chain, so it is
1493
+ * not added to `getSpending()` or the cost log, and reports `costUsd: 0`.
1494
+ */
1495
+ private bookPaid;
1482
1496
  /**
1483
1497
  * Sign a payment header and return the PAYMENT-SIGNATURE value.
1484
1498
  * Extracted to share logic between streaming and non-streaming flows.
package/dist/index.d.ts CHANGED
@@ -230,6 +230,13 @@ interface Settlement {
230
230
  network?: string;
231
231
  /** Present and false only when the gateway reported a failed settlement. */
232
232
  success?: false;
233
+ /**
234
+ * `"free-fallback"` when the gateway served a paid request from a free
235
+ * fallback model and skipped settlement (`X-Settlement-Skipped`): nothing
236
+ * moved on chain, so `costUsd` is 0 and nothing was added to `getSpending()`.
237
+ * `quotedUsd` still states what was signed.
238
+ */
239
+ skipped?: "free-fallback";
233
240
  }
234
241
  interface FunctionCall {
235
242
  name: string;
@@ -1479,6 +1486,13 @@ declare class LLMClient {
1479
1486
  private signFrom402;
1480
1487
  /** Send the signed payment and read the answer. The payment may settle from here on. */
1481
1488
  private sendPaid;
1489
+ /**
1490
+ * Book a served, paid chat call and attach its cost. A response the gateway
1491
+ * served from a free fallback with settlement skipped
1492
+ * (`X-Settlement-Skipped: free-fallback`) moved nothing on chain, so it is
1493
+ * not added to `getSpending()` or the cost log, and reports `costUsd: 0`.
1494
+ */
1495
+ private bookPaid;
1482
1496
  /**
1483
1497
  * Sign a payment header and return the PAYMENT-SIGNATURE value.
1484
1498
  * Extracted to share logic between streaming and non-streaming flows.
package/dist/index.js CHANGED
@@ -423,7 +423,15 @@ function readSettlement(response, quotedUsd, scheme) {
423
423
  };
424
424
  return { costUsd, settlement };
425
425
  }
426
+ function settlementSkipped(response) {
427
+ return response.headers.get("X-Settlement-Skipped") === "free-fallback";
428
+ }
426
429
  function withCost(body, response, bookedUsd, scheme) {
430
+ if (settlementSkipped(response)) {
431
+ body.costUsd = 0;
432
+ body.settlement = { ...readSettlement(response, bookedUsd, scheme).settlement, skipped: "free-fallback" };
433
+ return body;
434
+ }
427
435
  body.costUsd = bookedUsd;
428
436
  body.settlement = readSettlement(response, bookedUsd, scheme).settlement;
429
437
  return body;
@@ -4694,7 +4702,7 @@ function getCostSummary() {
4694
4702
  }
4695
4703
 
4696
4704
  // src/version.ts
4697
- var SDK_VERSION = "3.22.0";
4705
+ var SDK_VERSION = "3.22.1";
4698
4706
  var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
4699
4707
 
4700
4708
  // src/client.ts
@@ -5260,11 +5268,7 @@ var LLMClient = class _LLMClient {
5260
5268
  }
5261
5269
  throw new APIError(`API error after payment: ${retryResp2.status}`, retryResp2.status, sanitizeErrorResponse(errorBody));
5262
5270
  }
5263
- const costUsd2 = parseFloat(details.amount) / 1e6;
5264
- this.sessionCalls += 1;
5265
- this.sessionTotalUsd += costUsd2;
5266
- this.recordCost(url, costUsd2, { body, network: details.network });
5267
- return withCost(await this.parseChatResponse(retryResp2), retryResp2, costUsd2, "exact");
5271
+ return this.bookPaid(url, body, details, retryResp2);
5268
5272
  }
5269
5273
  }
5270
5274
  if (retryResponse.status === 402) {
@@ -5283,11 +5287,22 @@ var LLMClient = class _LLMClient {
5283
5287
  sanitizeErrorResponse(errorBody)
5284
5288
  );
5285
5289
  }
5290
+ return this.bookPaid(url, body, details, retryResponse);
5291
+ }
5292
+ /**
5293
+ * Book a served, paid chat call and attach its cost. A response the gateway
5294
+ * served from a free fallback with settlement skipped
5295
+ * (`X-Settlement-Skipped: free-fallback`) moved nothing on chain, so it is
5296
+ * not added to `getSpending()` or the cost log, and reports `costUsd: 0`.
5297
+ */
5298
+ async bookPaid(url, body, details, response) {
5286
5299
  const costUsd = parseFloat(details.amount) / 1e6;
5287
- this.sessionCalls += 1;
5288
- this.sessionTotalUsd += costUsd;
5289
- this.recordCost(url, costUsd, { body, network: details.network });
5290
- return withCost(await this.parseChatResponse(retryResponse), retryResponse, costUsd, "exact");
5300
+ if (!settlementSkipped(response)) {
5301
+ this.sessionCalls += 1;
5302
+ this.sessionTotalUsd += costUsd;
5303
+ this.recordCost(url, costUsd, { body, network: details.network });
5304
+ }
5305
+ return withCost(await this.parseChatResponse(response), response, costUsd, "exact");
5291
5306
  }
5292
5307
  /**
5293
5308
  * Sign a payment header and return the PAYMENT-SIGNATURE value.
@@ -13274,7 +13289,7 @@ var SolanaLLMClient = class {
13274
13289
  throw withDisposition(error, "paid-or-in-doubt");
13275
13290
  }
13276
13291
  await this.assertPaid(retryResponse);
13277
- this.recordSettlement(costUsd);
13292
+ if (!settlementSkipped(retryResponse)) this.recordSettlement(costUsd);
13278
13293
  const paid = await this.readPaidJson(retryResponse);
13279
13294
  return withCost(paid, retryResponse, costUsd, "exact");
13280
13295
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/llm",
3
- "version": "3.22.0",
3
+ "version": "3.22.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",