@blockrun/llm 2.7.0 → 2.9.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/dist/index.js CHANGED
@@ -1360,16 +1360,18 @@ var LLMClient = class _LLMClient {
1360
1360
  return data.data || [];
1361
1361
  }
1362
1362
  /**
1363
- * Edit an image using img2img.
1363
+ * Edit an image using img2img, optionally fusing multiple source images.
1364
1364
  *
1365
1365
  * @param prompt - Text description of the desired edit
1366
- * @param image - Base64-encoded image or URL of the source image
1366
+ * @param image - A base64 `data:image/...` URI, or an array of 2–4 such URIs
1367
+ * to fuse (image fusion). Caps: `openai/*` up to 4, `google/*` up to 3.
1368
+ * A `mask` cannot be combined with multiple source images.
1367
1369
  * @param options - Optional edit parameters
1368
1370
  * @returns ImageResponse with edited image URLs
1369
1371
  */
1370
1372
  async imageEdit(prompt, image, options) {
1371
1373
  const body = {
1372
- model: options?.model || "openai/gpt-image-1",
1374
+ model: options?.model || "openai/gpt-image-2",
1373
1375
  prompt,
1374
1376
  image,
1375
1377
  size: options?.size || "1024x1024",
@@ -1869,20 +1871,37 @@ var ImageClient = class {
1869
1871
  return this.requestWithPayment("/v1/images/generations", body);
1870
1872
  }
1871
1873
  /**
1872
- * Edit an image using img2img.
1874
+ * Edit an image using img2img, optionally fusing multiple source images.
1875
+ *
1876
+ * Pass a single `data:image/...` base64 data URI to edit one image, or an
1877
+ * array of 2–4 data URIs to fuse them (image fusion) — e.g. a reference photo
1878
+ * plus a brand logo. The server caps fusion per provider: `openai/*` accepts
1879
+ * up to 4 source images, `google/*` (Nano Banana) up to 3. A `mask` cannot be
1880
+ * combined with multiple source images.
1881
+ *
1882
+ * Edit-capable models: `openai/gpt-image-1`, `openai/gpt-image-2`,
1883
+ * `google/nano-banana`, `google/nano-banana-pro`.
1873
1884
  *
1874
1885
  * @param prompt - Text description of the desired edit
1875
- * @param image - Base64-encoded image or URL of the source image
1886
+ * @param image - A base64 `data:image/...` URI, or an array of 2–4 such URIs to fuse
1876
1887
  * @param options - Optional edit parameters
1877
1888
  * @returns ImageResponse with edited image URLs
1878
1889
  *
1879
1890
  * @example
1880
- * const result = await client.edit('Make it a painting', imageBase64);
1881
- * console.log(result.data[0].url);
1891
+ * // Single-image edit
1892
+ * const result = await client.edit('Make it a painting', imageDataUri);
1893
+ *
1894
+ * @example
1895
+ * // Multi-image fusion (Nano Banana): blend a subject with a brand logo
1896
+ * const fused = await client.edit(
1897
+ * 'Place the logo on the t-shirt',
1898
+ * [subjectDataUri, logoDataUri],
1899
+ * { model: 'google/nano-banana' }
1900
+ * );
1882
1901
  */
1883
1902
  async edit(prompt, image, options) {
1884
1903
  const body = {
1885
- model: options?.model || "openai/gpt-image-1",
1904
+ model: options?.model || "openai/gpt-image-2",
1886
1905
  prompt,
1887
1906
  image,
1888
1907
  size: options?.size || "1024x1024",
@@ -2898,15 +2917,18 @@ var PhoneClient = class {
2898
2917
  }
2899
2918
  };
2900
2919
 
2901
- // src/search.ts
2920
+ // src/portrait.ts
2902
2921
  import { privateKeyToAccount as privateKeyToAccount7 } from "viem/accounts";
2903
2922
  var DEFAULT_API_URL7 = "https://blockrun.ai/api";
2904
2923
  var DEFAULT_TIMEOUT7 = 6e4;
2905
- var SearchClient = class {
2924
+ var PORTRAIT_ENROLLMENT_PRICE_USD = 0.01;
2925
+ var PortraitClient = class {
2906
2926
  account;
2907
2927
  privateKey;
2908
2928
  apiUrl;
2909
2929
  timeout;
2930
+ sessionTotalUsd = 0;
2931
+ sessionCalls = 0;
2910
2932
  constructor(options = {}) {
2911
2933
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
2912
2934
  const privateKey = options.privateKey || envKey;
@@ -2923,6 +2945,157 @@ var SearchClient = class {
2923
2945
  this.apiUrl = apiUrl.replace(/\/$/, "");
2924
2946
  this.timeout = options.timeout || DEFAULT_TIMEOUT7;
2925
2947
  }
2948
+ /** EVM wallet address used for payments. */
2949
+ getWalletAddress() {
2950
+ return this.account.address;
2951
+ }
2952
+ /** Session-cumulative USD spend + call count across this client instance. */
2953
+ getSpending() {
2954
+ return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
2955
+ }
2956
+ /**
2957
+ * Enroll a Virtual Portrait from a face image URL. $0.01 (promo).
2958
+ *
2959
+ * Payment is settled only after Token360 confirms the enrollment, so failed
2960
+ * enrollments never charge your wallet.
2961
+ *
2962
+ * @param options.name Display name (1–64 chars).
2963
+ * @param options.imageUrl Public HTTPS URL to a JPG/PNG/WEBP image (≤10 MB).
2964
+ * @returns The enrollment record, including `asset_id` (`ta_xxxxxx`).
2965
+ */
2966
+ async enroll(options) {
2967
+ const name = typeof options?.name === "string" ? options.name.trim() : "";
2968
+ if (name.length < 1 || name.length > 64) {
2969
+ throw new Error("name is required and must be 1\u201364 characters");
2970
+ }
2971
+ const imageUrl = typeof options?.imageUrl === "string" ? options.imageUrl.trim() : "";
2972
+ if (!/^https?:\/\//i.test(imageUrl)) {
2973
+ throw new Error(
2974
+ "imageUrl must be a public http(s) URL to a JPG/PNG/WEBP image"
2975
+ );
2976
+ }
2977
+ const data = await this.request({
2978
+ name,
2979
+ image_url: imageUrl
2980
+ });
2981
+ return data;
2982
+ }
2983
+ // ─── Internals ─────────────────────────────────────────────────────────
2984
+ async request(body) {
2985
+ const url = `${this.apiUrl}/v1/portrait/enroll`;
2986
+ const response = await this.fetchWithTimeout(url, {
2987
+ method: "POST",
2988
+ headers: { "Content-Type": "application/json" },
2989
+ body: JSON.stringify(body)
2990
+ });
2991
+ if (response.status === 402) {
2992
+ return this.handlePaymentAndRetry(url, body, response);
2993
+ }
2994
+ return this.unwrap(response, false);
2995
+ }
2996
+ async handlePaymentAndRetry(url, body, response) {
2997
+ let paymentHeader = response.headers.get("payment-required");
2998
+ if (!paymentHeader) {
2999
+ try {
3000
+ const rb = await response.json();
3001
+ if (rb.x402 || rb.accepts) paymentHeader = btoa(JSON.stringify(rb));
3002
+ } catch {
3003
+ }
3004
+ }
3005
+ if (!paymentHeader) {
3006
+ throw new PaymentError("402 response but no payment requirements found");
3007
+ }
3008
+ const paymentRequired = parsePaymentRequired(paymentHeader);
3009
+ const details = extractPaymentDetails(paymentRequired);
3010
+ const paymentPayload = await createPaymentPayload(
3011
+ this.privateKey,
3012
+ this.account.address,
3013
+ details.recipient,
3014
+ details.amount,
3015
+ details.network || "eip155:8453",
3016
+ {
3017
+ resourceUrl: details.resource?.url || url,
3018
+ resourceDescription: details.resource?.description || "BlockRun Virtual Portrait",
3019
+ maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
3020
+ extra: details.extra
3021
+ }
3022
+ );
3023
+ const retry = await this.fetchWithTimeout(url, {
3024
+ method: "POST",
3025
+ headers: {
3026
+ "Content-Type": "application/json",
3027
+ "PAYMENT-SIGNATURE": paymentPayload
3028
+ },
3029
+ body: JSON.stringify(body)
3030
+ });
3031
+ if (retry.status === 402) {
3032
+ throw new PaymentError("Payment was rejected. Check your wallet balance.");
3033
+ }
3034
+ const data = await this.unwrap(retry, true);
3035
+ const costUsd = Number.parseFloat(details.amount) / 1e6;
3036
+ this.sessionCalls += 1;
3037
+ this.sessionTotalUsd += costUsd;
3038
+ if (data && typeof data === "object" && !("txHash" in data)) {
3039
+ const settlement = data.settlement;
3040
+ if (settlement?.tx_hash) {
3041
+ data.txHash = settlement.tx_hash;
3042
+ }
3043
+ }
3044
+ return data;
3045
+ }
3046
+ async unwrap(response, afterPayment) {
3047
+ if (response.ok) {
3048
+ return response.json();
3049
+ }
3050
+ let errorBody;
3051
+ try {
3052
+ errorBody = await response.json();
3053
+ } catch {
3054
+ errorBody = { error: "Request failed" };
3055
+ }
3056
+ const prefix = afterPayment ? "API error after payment" : "API error";
3057
+ throw new APIError(
3058
+ `${prefix}: ${response.status}`,
3059
+ response.status,
3060
+ sanitizeErrorResponse(errorBody)
3061
+ );
3062
+ }
3063
+ async fetchWithTimeout(url, init) {
3064
+ const controller = new AbortController();
3065
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
3066
+ try {
3067
+ return await fetch(url, { ...init, signal: controller.signal });
3068
+ } finally {
3069
+ clearTimeout(timeoutId);
3070
+ }
3071
+ }
3072
+ };
3073
+
3074
+ // src/search.ts
3075
+ import { privateKeyToAccount as privateKeyToAccount8 } from "viem/accounts";
3076
+ var DEFAULT_API_URL8 = "https://blockrun.ai/api";
3077
+ var DEFAULT_TIMEOUT8 = 6e4;
3078
+ var SearchClient = class {
3079
+ account;
3080
+ privateKey;
3081
+ apiUrl;
3082
+ timeout;
3083
+ constructor(options = {}) {
3084
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
3085
+ const privateKey = options.privateKey || envKey;
3086
+ if (!privateKey) {
3087
+ throw new Error(
3088
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
3089
+ );
3090
+ }
3091
+ validatePrivateKey(privateKey);
3092
+ this.privateKey = privateKey;
3093
+ this.account = privateKeyToAccount8(privateKey);
3094
+ const apiUrl = options.apiUrl || DEFAULT_API_URL8;
3095
+ validateApiUrl(apiUrl);
3096
+ this.apiUrl = apiUrl.replace(/\/$/, "");
3097
+ this.timeout = options.timeout || DEFAULT_TIMEOUT8;
3098
+ }
2926
3099
  async search(query, options) {
2927
3100
  if (!query || query.length > 1e3) {
2928
3101
  throw new Error("query must be 1-1000 characters");
@@ -3035,9 +3208,9 @@ var SearchClient = class {
3035
3208
  };
3036
3209
 
3037
3210
  // src/x-client.ts
3038
- import { privateKeyToAccount as privateKeyToAccount8 } from "viem/accounts";
3039
- var DEFAULT_API_URL8 = "https://blockrun.ai/api";
3040
- var DEFAULT_TIMEOUT8 = 6e4;
3211
+ import { privateKeyToAccount as privateKeyToAccount9 } from "viem/accounts";
3212
+ var DEFAULT_API_URL9 = "https://blockrun.ai/api";
3213
+ var DEFAULT_TIMEOUT9 = 6e4;
3041
3214
  var XClient = class _XClient {
3042
3215
  account;
3043
3216
  privateKey;
@@ -3060,11 +3233,11 @@ var XClient = class _XClient {
3060
3233
  }
3061
3234
  validatePrivateKey(privateKey);
3062
3235
  this.privateKey = privateKey;
3063
- this.account = privateKeyToAccount8(privateKey);
3064
- const apiUrl = options.apiUrl || DEFAULT_API_URL8;
3236
+ this.account = privateKeyToAccount9(privateKey);
3237
+ const apiUrl = options.apiUrl || DEFAULT_API_URL9;
3065
3238
  validateApiUrl(apiUrl);
3066
3239
  this.apiUrl = apiUrl.replace(/\/$/, "");
3067
- this.timeout = options.timeout || DEFAULT_TIMEOUT8;
3240
+ this.timeout = options.timeout || DEFAULT_TIMEOUT9;
3068
3241
  }
3069
3242
  // ───────── User endpoints ─────────
3070
3243
  userLookup(usernames) {
@@ -3242,9 +3415,9 @@ var XClient = class _XClient {
3242
3415
  };
3243
3416
 
3244
3417
  // src/price.ts
3245
- import { privateKeyToAccount as privateKeyToAccount9 } from "viem/accounts";
3246
- var DEFAULT_API_URL9 = "https://blockrun.ai/api";
3247
- var DEFAULT_TIMEOUT9 = 3e4;
3418
+ import { privateKeyToAccount as privateKeyToAccount10 } from "viem/accounts";
3419
+ var DEFAULT_API_URL10 = "https://blockrun.ai/api";
3420
+ var DEFAULT_TIMEOUT10 = 3e4;
3248
3421
  var PriceClient = class {
3249
3422
  account = null;
3250
3423
  privateKey = null;
@@ -3262,12 +3435,12 @@ var PriceClient = class {
3262
3435
  if (privateKey) {
3263
3436
  validatePrivateKey(privateKey);
3264
3437
  this.privateKey = privateKey;
3265
- this.account = privateKeyToAccount9(privateKey);
3438
+ this.account = privateKeyToAccount10(privateKey);
3266
3439
  }
3267
- const apiUrl = options.apiUrl || DEFAULT_API_URL9;
3440
+ const apiUrl = options.apiUrl || DEFAULT_API_URL10;
3268
3441
  validateApiUrl(apiUrl);
3269
3442
  this.apiUrl = apiUrl.replace(/\/$/, "");
3270
- this.timeout = options.timeout || DEFAULT_TIMEOUT9;
3443
+ this.timeout = options.timeout || DEFAULT_TIMEOUT10;
3271
3444
  }
3272
3445
  async price(category, symbol, options) {
3273
3446
  if (!symbol) throw new Error("symbol is required");
@@ -3446,9 +3619,9 @@ function buildUrl(base, query) {
3446
3619
  }
3447
3620
 
3448
3621
  // src/surf.ts
3449
- import { privateKeyToAccount as privateKeyToAccount10 } from "viem/accounts";
3450
- var DEFAULT_API_URL10 = "https://blockrun.ai/api";
3451
- var DEFAULT_TIMEOUT10 = 6e4;
3622
+ import { privateKeyToAccount as privateKeyToAccount11 } from "viem/accounts";
3623
+ var DEFAULT_API_URL11 = "https://blockrun.ai/api";
3624
+ var DEFAULT_TIMEOUT11 = 6e4;
3452
3625
  var SURF_PREFIX = "/v1/surf";
3453
3626
  var SurfClient = class {
3454
3627
  account;
@@ -3465,11 +3638,11 @@ var SurfClient = class {
3465
3638
  }
3466
3639
  validatePrivateKey(privateKey);
3467
3640
  this.privateKey = privateKey;
3468
- this.account = privateKeyToAccount10(privateKey);
3469
- const apiUrl = options.apiUrl || DEFAULT_API_URL10;
3641
+ this.account = privateKeyToAccount11(privateKey);
3642
+ const apiUrl = options.apiUrl || DEFAULT_API_URL11;
3470
3643
  validateApiUrl(apiUrl);
3471
3644
  this.apiUrl = apiUrl.replace(/\/$/, "");
3472
- this.timeout = options.timeout || DEFAULT_TIMEOUT10;
3645
+ this.timeout = options.timeout || DEFAULT_TIMEOUT11;
3473
3646
  }
3474
3647
  /**
3475
3648
  * GET a Surf endpoint. `path` is everything after `/v1/surf` (a leading
@@ -3601,9 +3774,9 @@ var SurfClient = class {
3601
3774
  };
3602
3775
 
3603
3776
  // src/blockrun.ts
3604
- import { privateKeyToAccount as privateKeyToAccount11 } from "viem/accounts";
3605
- var DEFAULT_API_URL11 = "https://blockrun.ai/api";
3606
- var DEFAULT_TIMEOUT11 = 6e4;
3777
+ import { privateKeyToAccount as privateKeyToAccount12 } from "viem/accounts";
3778
+ var DEFAULT_API_URL12 = "https://blockrun.ai/api";
3779
+ var DEFAULT_TIMEOUT12 = 6e4;
3607
3780
  var DEFAULT_POLL_INTERVAL_MS = 5e3;
3608
3781
  var DEFAULT_POLL_BUDGET_MS = 3e5;
3609
3782
  var MAX_SIGNED_AUTH_SECONDS = 600;
@@ -3624,11 +3797,11 @@ var BlockrunClient = class {
3624
3797
  }
3625
3798
  validatePrivateKey(privateKey);
3626
3799
  this.privateKey = privateKey;
3627
- this.account = privateKeyToAccount11(privateKey);
3628
- const apiUrl = options.apiUrl || DEFAULT_API_URL11;
3800
+ this.account = privateKeyToAccount12(privateKey);
3801
+ const apiUrl = options.apiUrl || DEFAULT_API_URL12;
3629
3802
  validateApiUrl(apiUrl);
3630
3803
  this.apiUrl = apiUrl.replace(/\/$/, "");
3631
- this.timeout = options.timeout || DEFAULT_TIMEOUT11;
3804
+ this.timeout = options.timeout || DEFAULT_TIMEOUT12;
3632
3805
  }
3633
3806
  /**
3634
3807
  * GET a BlockRun endpoint. `path` is everything after `/api` (a leading
@@ -3979,7 +4152,7 @@ function sleep(ms) {
3979
4152
  }
3980
4153
 
3981
4154
  // src/wallet.ts
3982
- import { privateKeyToAccount as privateKeyToAccount12, generatePrivateKey } from "viem/accounts";
4155
+ import { privateKeyToAccount as privateKeyToAccount13, generatePrivateKey } from "viem/accounts";
3983
4156
  import * as fs2 from "fs";
3984
4157
  import * as path2 from "path";
3985
4158
  import * as os2 from "os";
@@ -3989,7 +4162,7 @@ var WALLET_DIR = path2.join(os2.homedir(), ".blockrun");
3989
4162
  var WALLET_FILE = path2.join(WALLET_DIR, ".session");
3990
4163
  function createWallet() {
3991
4164
  const privateKey = generatePrivateKey();
3992
- const account = privateKeyToAccount12(privateKey);
4165
+ const account = privateKeyToAccount13(privateKey);
3993
4166
  return {
3994
4167
  address: account.address,
3995
4168
  privateKey
@@ -4045,12 +4218,12 @@ function loadWallet() {
4045
4218
  function getOrCreateWallet() {
4046
4219
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
4047
4220
  if (envKey) {
4048
- const account = privateKeyToAccount12(envKey);
4221
+ const account = privateKeyToAccount13(envKey);
4049
4222
  return { address: account.address, privateKey: envKey, isNew: false };
4050
4223
  }
4051
4224
  const fileKey = loadWallet();
4052
4225
  if (fileKey) {
4053
- const account = privateKeyToAccount12(fileKey);
4226
+ const account = privateKeyToAccount13(fileKey);
4054
4227
  return { address: account.address, privateKey: fileKey, isNew: false };
4055
4228
  }
4056
4229
  const { address, privateKey } = createWallet();
@@ -4060,11 +4233,11 @@ function getOrCreateWallet() {
4060
4233
  function getWalletAddress() {
4061
4234
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
4062
4235
  if (envKey) {
4063
- return privateKeyToAccount12(envKey).address;
4236
+ return privateKeyToAccount13(envKey).address;
4064
4237
  }
4065
4238
  const fileKey = loadWallet();
4066
4239
  if (fileKey) {
4067
- return privateKeyToAccount12(fileKey).address;
4240
+ return privateKeyToAccount13(fileKey).address;
4068
4241
  }
4069
4242
  return null;
4070
4243
  }
@@ -4244,7 +4417,7 @@ async function getOrCreateSolanaWallet() {
4244
4417
  // src/solana-client.ts
4245
4418
  var SOLANA_API_URL = "https://sol.blockrun.ai/api";
4246
4419
  var DEFAULT_MAX_TOKENS2 = 1024;
4247
- var DEFAULT_TIMEOUT12 = 6e4;
4420
+ var DEFAULT_TIMEOUT13 = 6e4;
4248
4421
  var SDK_VERSION2 = "0.3.0";
4249
4422
  var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
4250
4423
  var DEFAULT_SOLANA_RPC_URL = "https://sol.blockrun.ai/api/v1/solana/rpc";
@@ -4294,7 +4467,7 @@ var SolanaLLMClient = class {
4294
4467
  const rpc = resolveRpcConfig(options.rpcUrl, options.rpcHeaders);
4295
4468
  this.rpcUrl = rpc.url;
4296
4469
  this.rpcHeaders = rpc.headers;
4297
- this.timeout = options.timeout || DEFAULT_TIMEOUT12;
4470
+ this.timeout = options.timeout || DEFAULT_TIMEOUT13;
4298
4471
  }
4299
4472
  /** Get Solana wallet address (public key in base58). */
4300
4473
  async getWalletAddress() {
@@ -4375,7 +4548,7 @@ var SolanaLLMClient = class {
4375
4548
  /** Edit an image using img2img (Solana payment). */
4376
4549
  async imageEdit(prompt, image, options) {
4377
4550
  const body = {
4378
- model: options?.model || "openai/gpt-image-1",
4551
+ model: options?.model || "openai/gpt-image-2",
4379
4552
  prompt,
4380
4553
  image,
4381
4554
  size: options?.size || "1024x1024",
@@ -5204,7 +5377,7 @@ var OpenAI = class {
5204
5377
  };
5205
5378
 
5206
5379
  // src/anthropic-compat.ts
5207
- import { privateKeyToAccount as privateKeyToAccount13 } from "viem/accounts";
5380
+ import { privateKeyToAccount as privateKeyToAccount14 } from "viem/accounts";
5208
5381
  var AnthropicClient = class {
5209
5382
  _client = null;
5210
5383
  _clientPromise = null;
@@ -5217,7 +5390,7 @@ var AnthropicClient = class {
5217
5390
  const key = options.privateKey ?? wallet.privateKey;
5218
5391
  validatePrivateKey(key);
5219
5392
  this._privateKey = key;
5220
- this._account = privateKeyToAccount13(this._privateKey);
5393
+ this._account = privateKeyToAccount14(this._privateKey);
5221
5394
  const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
5222
5395
  validateApiUrl(apiUrl);
5223
5396
  this._apiUrl = apiUrl.replace(/\/$/, "");
@@ -5323,8 +5496,10 @@ export {
5323
5496
  MusicClient,
5324
5497
  OpenAI,
5325
5498
  PHONE_PRICES,
5499
+ PORTRAIT_ENROLLMENT_PRICE_USD,
5326
5500
  PaymentError,
5327
5501
  PhoneClient,
5502
+ PortraitClient,
5328
5503
  PriceClient,
5329
5504
  SOLANA_NETWORK,
5330
5505
  SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/llm",
3
- "version": "2.7.0",
3
+ "version": "2.9.1",
4
4
  "type": "module",
5
5
  "description": "BlockRun SDK - Pay-per-request AI (LLM, Image, Video, Music, Voice) via x402 on Base and Solana",
6
6
  "main": "dist/index.cjs",