@blockrun/llm 3.24.9 → 3.24.10
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 +5 -2
- package/dist/index.cjs +64 -4
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +64 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -635,7 +635,10 @@ console.log(res.costUsd, res.settlement); // what you paid, and the tx
|
|
|
635
635
|
```
|
|
636
636
|
|
|
637
637
|
`costUsd`, `settlement` and the per-call `timeout` work the same on `LLMClient`
|
|
638
|
-
(Base / Arc).
|
|
638
|
+
(Base / Arc). Both clients default to a 600 s request timeout
|
|
639
|
+
(`BLOCKRUN_CHAT_TIMEOUT`, in seconds, overrides it; the `timeout` option, in
|
|
640
|
+
ms, overrides both): a call aborted after its payment was sent may already be
|
|
641
|
+
charged, so a batch payment ends unresolved rather than paid again. `costUsd` is what the call added to `getSpending()`: the signed
|
|
639
642
|
price under `exact`, the metered `extra.chargedAmount` under batch settlement,
|
|
640
643
|
`0` for a free model; it is undefined in API-key mode (billed to the account).
|
|
641
644
|
When the gateway answers a paid request from a free fallback model it skips
|
|
@@ -1695,7 +1698,7 @@ const configured = new LLMClient({
|
|
|
1695
1698
|
| `SOLANA_RPC_URL` | Solana RPC for payments and balance (also `rpcUrl`) |
|
|
1696
1699
|
| `SOLANA_RPC_API_KEY` / `SOLANA_RPC_HEADERS` | Header auth for that RPC (also `rpcHeaders`) |
|
|
1697
1700
|
| `BASE_RPC_URL` | Base RPC tried first by `LLMClient.getBalance()` |
|
|
1698
|
-
| `BLOCKRUN_CHAT_TIMEOUT` | `LLMClient` default timeout, in **seconds** (default 600) |
|
|
1701
|
+
| `BLOCKRUN_CHAT_TIMEOUT` | `LLMClient` and `SolanaLLMClient` default timeout, in **seconds** (default 600) |
|
|
1699
1702
|
| `BLOCKRUN_HOME` | Base directory for the Base wallet files (security-sensitive, see [Wallets](#one-wallet-across-every-blockrun-product)) |
|
|
1700
1703
|
|
|
1701
1704
|
`BLOCKRUN_SOL_OPERATOR` is **not** an environment variable or a secret. It is
|
package/dist/index.cjs
CHANGED
|
@@ -5120,7 +5120,7 @@ function getCostSummary() {
|
|
|
5120
5120
|
}
|
|
5121
5121
|
|
|
5122
5122
|
// src/version.ts
|
|
5123
|
-
var SDK_VERSION = "3.24.
|
|
5123
|
+
var SDK_VERSION = "3.24.10";
|
|
5124
5124
|
var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
|
|
5125
5125
|
|
|
5126
5126
|
// src/client.ts
|
|
@@ -10902,6 +10902,38 @@ function withoutClientSignedBatch(paymentRequired) {
|
|
|
10902
10902
|
const accepts = paymentRequired.accepts ?? [];
|
|
10903
10903
|
return accepts.some(clientSignedBatch) ? { ...paymentRequired, accepts: accepts.filter((accept) => !clientSignedBatch(accept)) } : paymentRequired;
|
|
10904
10904
|
}
|
|
10905
|
+
var DEPOSIT_BLOCKHASH_TTL_MS = 1e4;
|
|
10906
|
+
var MAX_DEPOSIT_BLOCKHASH_ENDPOINTS = 8;
|
|
10907
|
+
var depositBlockhashes = /* @__PURE__ */ new Map();
|
|
10908
|
+
async function finalizedBlockhash(rpcUrl, rpcHeaders) {
|
|
10909
|
+
const cached = depositBlockhashes.get(rpcUrl);
|
|
10910
|
+
if (cached && Date.now() - cached.fetchedAt < DEPOSIT_BLOCKHASH_TTL_MS) return cached;
|
|
10911
|
+
const result = await rpcRequest(rpcUrl, "getLatestBlockhash", [{ commitment: "finalized" }], rpcHeaders);
|
|
10912
|
+
const blockhash = result.value?.blockhash;
|
|
10913
|
+
if (typeof blockhash !== "string" || !blockhash) throw new Error("getLatestBlockhash returned no blockhash");
|
|
10914
|
+
const entry = {
|
|
10915
|
+
blockhash,
|
|
10916
|
+
lastValidBlockHeight: rpcInteger(result.value?.lastValidBlockHeight, "getLatestBlockhash lastValidBlockHeight"),
|
|
10917
|
+
fetchedAt: Date.now()
|
|
10918
|
+
};
|
|
10919
|
+
depositBlockhashes.delete(rpcUrl);
|
|
10920
|
+
depositBlockhashes.set(rpcUrl, entry);
|
|
10921
|
+
while (depositBlockhashes.size > MAX_DEPOSIT_BLOCKHASH_ENDPOINTS) {
|
|
10922
|
+
depositBlockhashes.delete(depositBlockhashes.keys().next().value);
|
|
10923
|
+
}
|
|
10924
|
+
return entry;
|
|
10925
|
+
}
|
|
10926
|
+
function withDepositBlockhash(paymentRequired, blockhash) {
|
|
10927
|
+
const accepts = paymentRequired.accepts ?? [];
|
|
10928
|
+
const lacking = (accept) => accept.scheme === BATCH_SCHEME && !accept.extra?.recentBlockhash;
|
|
10929
|
+
if (!accepts.some(lacking)) return paymentRequired;
|
|
10930
|
+
return {
|
|
10931
|
+
...paymentRequired,
|
|
10932
|
+
accepts: accepts.map(
|
|
10933
|
+
(accept) => lacking(accept) ? { ...accept, extra: { ...accept.extra, recentBlockhash: blockhash.blockhash, lastValidBlockHeight: blockhash.lastValidBlockHeight } } : accept
|
|
10934
|
+
)
|
|
10935
|
+
};
|
|
10936
|
+
}
|
|
10905
10937
|
var PAYMENT_IDENTIFIER = "payment-identifier";
|
|
10906
10938
|
function withPaymentIdentifier(paymentRequired) {
|
|
10907
10939
|
const declared = paymentRequired.extensions?.[PAYMENT_IDENTIFIER];
|
|
@@ -12391,7 +12423,8 @@ var SolanaBatchPayer = class {
|
|
|
12391
12423
|
const http = (await this.build(wallet)).http;
|
|
12392
12424
|
try {
|
|
12393
12425
|
await this.prepareTopUp(wallet, paymentRequired);
|
|
12394
|
-
|
|
12426
|
+
const required = await this.withDepositBlockhash(wallet, withoutClientSignedBatch(paymentRequired));
|
|
12427
|
+
return { http, payload: await http.createPaymentPayload(withPaymentIdentifier(required)) };
|
|
12395
12428
|
} catch (err) {
|
|
12396
12429
|
if (pass > 0 || !isResyncRequired(err) || wallet.resyncs.size === 0) throw err;
|
|
12397
12430
|
} finally {
|
|
@@ -12399,6 +12432,34 @@ var SolanaBatchPayer = class {
|
|
|
12399
12432
|
}
|
|
12400
12433
|
}
|
|
12401
12434
|
}
|
|
12435
|
+
/**
|
|
12436
|
+
* The 402 to build this payment from: with a finalized blockhash
|
|
12437
|
+
* ({@link withDepositBlockhash}) when the payment will likely carry a
|
|
12438
|
+
* deposit (no usable record for the trusted accept's channel, so an open,
|
|
12439
|
+
* or a top-up {@link prepareTopUp} just sized). An authorization signs no
|
|
12440
|
+
* transaction and costs no RPC read. Best effort: a failed read leaves the
|
|
12441
|
+
* 402 as it is, and `@x402/svm` fetches its own blockhash.
|
|
12442
|
+
*/
|
|
12443
|
+
async withDepositBlockhash(wallet, paymentRequired) {
|
|
12444
|
+
const accept = trustedBatchAccept(paymentRequired, this.init.options.operators);
|
|
12445
|
+
const key = accept ? channelKeyOf(accept) : void 0;
|
|
12446
|
+
if (!accept || accept.extra?.recentBlockhash) return paymentRequired;
|
|
12447
|
+
let deposit = wallet.topUp !== void 0;
|
|
12448
|
+
if (!deposit) {
|
|
12449
|
+
try {
|
|
12450
|
+
const record = key ? await wallet.book.base.get(key) : void 0;
|
|
12451
|
+
deposit = !record || typeof record.channelId !== "string" || record.pending !== void 0;
|
|
12452
|
+
} catch {
|
|
12453
|
+
deposit = true;
|
|
12454
|
+
}
|
|
12455
|
+
}
|
|
12456
|
+
if (!deposit) return paymentRequired;
|
|
12457
|
+
try {
|
|
12458
|
+
return withDepositBlockhash(paymentRequired, await finalizedBlockhash(this.init.rpcUrl, this.init.rpcHeaders));
|
|
12459
|
+
} catch {
|
|
12460
|
+
return paymentRequired;
|
|
12461
|
+
}
|
|
12462
|
+
}
|
|
12402
12463
|
/**
|
|
12403
12464
|
* Queue a re-read of a stored channel whose account is gone at finalized
|
|
12404
12465
|
* and at confirmed commitment (closed, its account reclaimed), anchored at
|
|
@@ -12705,7 +12766,6 @@ var SolanaBatchPayer = class {
|
|
|
12705
12766
|
// src/solana-client.ts
|
|
12706
12767
|
var SOLANA_API_URL = "https://sol.blockrun.ai/api";
|
|
12707
12768
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
12708
|
-
var DEFAULT_TIMEOUT14 = 6e4;
|
|
12709
12769
|
var STALE_BLOCKHASH_RETRY_BACKOFFS_MS = [500, 2e3];
|
|
12710
12770
|
var MAX_PAYMENT_FAILURE_BYTES = 64 * 1024;
|
|
12711
12771
|
var DEFAULT_VIDEO_MODEL = "xai/grok-imagine-video";
|
|
@@ -12873,7 +12933,7 @@ var SolanaLLMClient = class {
|
|
|
12873
12933
|
const rpc = resolveRpcConfig(options.rpcUrl, options.rpcHeaders);
|
|
12874
12934
|
this.rpcUrl = rpc.url;
|
|
12875
12935
|
this.rpcHeaders = rpc.headers;
|
|
12876
|
-
this.timeout = options.timeout ||
|
|
12936
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
12877
12937
|
if (options.batch && !this.apiAuth) {
|
|
12878
12938
|
this.batchPayer = new SolanaBatchPayer({
|
|
12879
12939
|
options: options.batch,
|
package/dist/index.d.cts
CHANGED
|
@@ -3508,6 +3508,15 @@ declare class SolanaBatchPayer {
|
|
|
3508
3508
|
* once.
|
|
3509
3509
|
*/
|
|
3510
3510
|
private createPayload;
|
|
3511
|
+
/**
|
|
3512
|
+
* The 402 to build this payment from: with a finalized blockhash
|
|
3513
|
+
* ({@link withDepositBlockhash}) when the payment will likely carry a
|
|
3514
|
+
* deposit (no usable record for the trusted accept's channel, so an open,
|
|
3515
|
+
* or a top-up {@link prepareTopUp} just sized). An authorization signs no
|
|
3516
|
+
* transaction and costs no RPC read. Best effort: a failed read leaves the
|
|
3517
|
+
* 402 as it is, and `@x402/svm` fetches its own blockhash.
|
|
3518
|
+
*/
|
|
3519
|
+
private withDepositBlockhash;
|
|
3511
3520
|
/**
|
|
3512
3521
|
* Queue a re-read of a stored channel whose account is gone at finalized
|
|
3513
3522
|
* and at confirmed commitment (closed, its account reclaimed), anchored at
|
|
@@ -3647,7 +3656,12 @@ interface SolanaLLMClientOptions extends ApiKeyOptions {
|
|
|
3647
3656
|
* (shortcut for `{ "x-api-key": "..." }`) env vars when omitted.
|
|
3648
3657
|
*/
|
|
3649
3658
|
rpcHeaders?: Record<string, string>;
|
|
3650
|
-
/**
|
|
3659
|
+
/**
|
|
3660
|
+
* Request timeout in milliseconds. Default: `BLOCKRUN_CHAT_TIMEOUT` (in
|
|
3661
|
+
* seconds) when set, else 600000, the same as `LLMClient`: a reasoning
|
|
3662
|
+
* model's long turn can take minutes, and a batch payment whose call is
|
|
3663
|
+
* aborted after it was sent ends unresolved.
|
|
3664
|
+
*/
|
|
3651
3665
|
timeout?: number;
|
|
3652
3666
|
/**
|
|
3653
3667
|
* Opt in to x402 batch-settlement (metered billing) for chat completions.
|
package/dist/index.d.ts
CHANGED
|
@@ -3508,6 +3508,15 @@ declare class SolanaBatchPayer {
|
|
|
3508
3508
|
* once.
|
|
3509
3509
|
*/
|
|
3510
3510
|
private createPayload;
|
|
3511
|
+
/**
|
|
3512
|
+
* The 402 to build this payment from: with a finalized blockhash
|
|
3513
|
+
* ({@link withDepositBlockhash}) when the payment will likely carry a
|
|
3514
|
+
* deposit (no usable record for the trusted accept's channel, so an open,
|
|
3515
|
+
* or a top-up {@link prepareTopUp} just sized). An authorization signs no
|
|
3516
|
+
* transaction and costs no RPC read. Best effort: a failed read leaves the
|
|
3517
|
+
* 402 as it is, and `@x402/svm` fetches its own blockhash.
|
|
3518
|
+
*/
|
|
3519
|
+
private withDepositBlockhash;
|
|
3511
3520
|
/**
|
|
3512
3521
|
* Queue a re-read of a stored channel whose account is gone at finalized
|
|
3513
3522
|
* and at confirmed commitment (closed, its account reclaimed), anchored at
|
|
@@ -3647,7 +3656,12 @@ interface SolanaLLMClientOptions extends ApiKeyOptions {
|
|
|
3647
3656
|
* (shortcut for `{ "x-api-key": "..." }`) env vars when omitted.
|
|
3648
3657
|
*/
|
|
3649
3658
|
rpcHeaders?: Record<string, string>;
|
|
3650
|
-
/**
|
|
3659
|
+
/**
|
|
3660
|
+
* Request timeout in milliseconds. Default: `BLOCKRUN_CHAT_TIMEOUT` (in
|
|
3661
|
+
* seconds) when set, else 600000, the same as `LLMClient`: a reasoning
|
|
3662
|
+
* model's long turn can take minutes, and a batch payment whose call is
|
|
3663
|
+
* aborted after it was sent ends unresolved.
|
|
3664
|
+
*/
|
|
3651
3665
|
timeout?: number;
|
|
3652
3666
|
/**
|
|
3653
3667
|
* Opt in to x402 batch-settlement (metered billing) for chat completions.
|
package/dist/index.js
CHANGED
|
@@ -4989,7 +4989,7 @@ function getCostSummary() {
|
|
|
4989
4989
|
}
|
|
4990
4990
|
|
|
4991
4991
|
// src/version.ts
|
|
4992
|
-
var SDK_VERSION = "3.24.
|
|
4992
|
+
var SDK_VERSION = "3.24.10";
|
|
4993
4993
|
var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
|
|
4994
4994
|
|
|
4995
4995
|
// src/client.ts
|
|
@@ -10771,6 +10771,38 @@ function withoutClientSignedBatch(paymentRequired) {
|
|
|
10771
10771
|
const accepts = paymentRequired.accepts ?? [];
|
|
10772
10772
|
return accepts.some(clientSignedBatch) ? { ...paymentRequired, accepts: accepts.filter((accept) => !clientSignedBatch(accept)) } : paymentRequired;
|
|
10773
10773
|
}
|
|
10774
|
+
var DEPOSIT_BLOCKHASH_TTL_MS = 1e4;
|
|
10775
|
+
var MAX_DEPOSIT_BLOCKHASH_ENDPOINTS = 8;
|
|
10776
|
+
var depositBlockhashes = /* @__PURE__ */ new Map();
|
|
10777
|
+
async function finalizedBlockhash(rpcUrl, rpcHeaders) {
|
|
10778
|
+
const cached = depositBlockhashes.get(rpcUrl);
|
|
10779
|
+
if (cached && Date.now() - cached.fetchedAt < DEPOSIT_BLOCKHASH_TTL_MS) return cached;
|
|
10780
|
+
const result = await rpcRequest(rpcUrl, "getLatestBlockhash", [{ commitment: "finalized" }], rpcHeaders);
|
|
10781
|
+
const blockhash = result.value?.blockhash;
|
|
10782
|
+
if (typeof blockhash !== "string" || !blockhash) throw new Error("getLatestBlockhash returned no blockhash");
|
|
10783
|
+
const entry = {
|
|
10784
|
+
blockhash,
|
|
10785
|
+
lastValidBlockHeight: rpcInteger(result.value?.lastValidBlockHeight, "getLatestBlockhash lastValidBlockHeight"),
|
|
10786
|
+
fetchedAt: Date.now()
|
|
10787
|
+
};
|
|
10788
|
+
depositBlockhashes.delete(rpcUrl);
|
|
10789
|
+
depositBlockhashes.set(rpcUrl, entry);
|
|
10790
|
+
while (depositBlockhashes.size > MAX_DEPOSIT_BLOCKHASH_ENDPOINTS) {
|
|
10791
|
+
depositBlockhashes.delete(depositBlockhashes.keys().next().value);
|
|
10792
|
+
}
|
|
10793
|
+
return entry;
|
|
10794
|
+
}
|
|
10795
|
+
function withDepositBlockhash(paymentRequired, blockhash) {
|
|
10796
|
+
const accepts = paymentRequired.accepts ?? [];
|
|
10797
|
+
const lacking = (accept) => accept.scheme === BATCH_SCHEME && !accept.extra?.recentBlockhash;
|
|
10798
|
+
if (!accepts.some(lacking)) return paymentRequired;
|
|
10799
|
+
return {
|
|
10800
|
+
...paymentRequired,
|
|
10801
|
+
accepts: accepts.map(
|
|
10802
|
+
(accept) => lacking(accept) ? { ...accept, extra: { ...accept.extra, recentBlockhash: blockhash.blockhash, lastValidBlockHeight: blockhash.lastValidBlockHeight } } : accept
|
|
10803
|
+
)
|
|
10804
|
+
};
|
|
10805
|
+
}
|
|
10774
10806
|
var PAYMENT_IDENTIFIER = "payment-identifier";
|
|
10775
10807
|
function withPaymentIdentifier(paymentRequired) {
|
|
10776
10808
|
const declared = paymentRequired.extensions?.[PAYMENT_IDENTIFIER];
|
|
@@ -12260,7 +12292,8 @@ var SolanaBatchPayer = class {
|
|
|
12260
12292
|
const http = (await this.build(wallet)).http;
|
|
12261
12293
|
try {
|
|
12262
12294
|
await this.prepareTopUp(wallet, paymentRequired);
|
|
12263
|
-
|
|
12295
|
+
const required = await this.withDepositBlockhash(wallet, withoutClientSignedBatch(paymentRequired));
|
|
12296
|
+
return { http, payload: await http.createPaymentPayload(withPaymentIdentifier(required)) };
|
|
12264
12297
|
} catch (err) {
|
|
12265
12298
|
if (pass > 0 || !isResyncRequired(err) || wallet.resyncs.size === 0) throw err;
|
|
12266
12299
|
} finally {
|
|
@@ -12268,6 +12301,34 @@ var SolanaBatchPayer = class {
|
|
|
12268
12301
|
}
|
|
12269
12302
|
}
|
|
12270
12303
|
}
|
|
12304
|
+
/**
|
|
12305
|
+
* The 402 to build this payment from: with a finalized blockhash
|
|
12306
|
+
* ({@link withDepositBlockhash}) when the payment will likely carry a
|
|
12307
|
+
* deposit (no usable record for the trusted accept's channel, so an open,
|
|
12308
|
+
* or a top-up {@link prepareTopUp} just sized). An authorization signs no
|
|
12309
|
+
* transaction and costs no RPC read. Best effort: a failed read leaves the
|
|
12310
|
+
* 402 as it is, and `@x402/svm` fetches its own blockhash.
|
|
12311
|
+
*/
|
|
12312
|
+
async withDepositBlockhash(wallet, paymentRequired) {
|
|
12313
|
+
const accept = trustedBatchAccept(paymentRequired, this.init.options.operators);
|
|
12314
|
+
const key = accept ? channelKeyOf(accept) : void 0;
|
|
12315
|
+
if (!accept || accept.extra?.recentBlockhash) return paymentRequired;
|
|
12316
|
+
let deposit = wallet.topUp !== void 0;
|
|
12317
|
+
if (!deposit) {
|
|
12318
|
+
try {
|
|
12319
|
+
const record = key ? await wallet.book.base.get(key) : void 0;
|
|
12320
|
+
deposit = !record || typeof record.channelId !== "string" || record.pending !== void 0;
|
|
12321
|
+
} catch {
|
|
12322
|
+
deposit = true;
|
|
12323
|
+
}
|
|
12324
|
+
}
|
|
12325
|
+
if (!deposit) return paymentRequired;
|
|
12326
|
+
try {
|
|
12327
|
+
return withDepositBlockhash(paymentRequired, await finalizedBlockhash(this.init.rpcUrl, this.init.rpcHeaders));
|
|
12328
|
+
} catch {
|
|
12329
|
+
return paymentRequired;
|
|
12330
|
+
}
|
|
12331
|
+
}
|
|
12271
12332
|
/**
|
|
12272
12333
|
* Queue a re-read of a stored channel whose account is gone at finalized
|
|
12273
12334
|
* and at confirmed commitment (closed, its account reclaimed), anchored at
|
|
@@ -12574,7 +12635,6 @@ var SolanaBatchPayer = class {
|
|
|
12574
12635
|
// src/solana-client.ts
|
|
12575
12636
|
var SOLANA_API_URL = "https://sol.blockrun.ai/api";
|
|
12576
12637
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
12577
|
-
var DEFAULT_TIMEOUT14 = 6e4;
|
|
12578
12638
|
var STALE_BLOCKHASH_RETRY_BACKOFFS_MS = [500, 2e3];
|
|
12579
12639
|
var MAX_PAYMENT_FAILURE_BYTES = 64 * 1024;
|
|
12580
12640
|
var DEFAULT_VIDEO_MODEL = "xai/grok-imagine-video";
|
|
@@ -12742,7 +12802,7 @@ var SolanaLLMClient = class {
|
|
|
12742
12802
|
const rpc = resolveRpcConfig(options.rpcUrl, options.rpcHeaders);
|
|
12743
12803
|
this.rpcUrl = rpc.url;
|
|
12744
12804
|
this.rpcHeaders = rpc.headers;
|
|
12745
|
-
this.timeout = options.timeout ||
|
|
12805
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
12746
12806
|
if (options.batch && !this.apiAuth) {
|
|
12747
12807
|
this.batchPayer = new SolanaBatchPayer({
|
|
12748
12808
|
options: options.batch,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/llm",
|
|
3
|
-
"version": "3.24.
|
|
3
|
+
"version": "3.24.10",
|
|
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",
|