@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/README.md +42 -3
- package/dist/index.cjs +223 -46
- package/dist/index.d.cts +157 -12
- package/dist/index.d.ts +157 -12
- package/dist/index.js +220 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,8 +84,8 @@ Four call shapes cover every endpoint type:
|
|
|
84
84
|
- `stream<T>(path, body?)` — async iterator over SSE chunks (chat)
|
|
85
85
|
|
|
86
86
|
The per-API client classes (`LLMClient`, `ImageClient`, `VideoClient`,
|
|
87
|
-
`VoiceClient`, `MusicClient`, `SearchClient`, `XClient`,
|
|
88
|
-
`SurfClient`) all remain — they will be soft-deprecated in 2.6 (rewritten as
|
|
87
|
+
`PortraitClient`, `VoiceClient`, `MusicClient`, `SearchClient`, `XClient`,
|
|
88
|
+
`PriceClient`, `SurfClient`) all remain — they will be soft-deprecated in 2.6 (rewritten as
|
|
89
89
|
shims over `BlockrunClient`) and removed in 3.0.
|
|
90
90
|
|
|
91
91
|
### Try It Free (No USDC Required)
|
|
@@ -406,7 +406,17 @@ All models below have been tested end-to-end via the TypeScript SDK (Feb 2026):
|
|
|
406
406
|
| `xai/grok-imagine-image-pro` | $0.07/image |
|
|
407
407
|
| `zai/cogview-4` | $0.015/image |
|
|
408
408
|
|
|
409
|
-
Image editing (`client.edit`)
|
|
409
|
+
Image editing (`client.edit`) via `/v1/images/image2image`: `openai/gpt-image-1`, `openai/gpt-image-2`, `google/nano-banana`, and `google/nano-banana-pro`. Pass a single base64 `data:image/...` URI to edit one image, or an array of 2–4 URIs to **fuse** them (e.g. a subject + a brand logo). Fusion caps: `openai/*` up to 4 source images, `google/*` up to 3. A `mask` cannot be combined with multiple source images.
|
|
410
|
+
|
|
411
|
+
```ts
|
|
412
|
+
// Multi-image fusion with Nano Banana
|
|
413
|
+
const fused = await client.edit(
|
|
414
|
+
"Place the logo on the t-shirt",
|
|
415
|
+
[subjectDataUri, logoDataUri],
|
|
416
|
+
{ model: "google/nano-banana" }
|
|
417
|
+
);
|
|
418
|
+
console.log(fused.data[0].url);
|
|
419
|
+
```
|
|
410
420
|
|
|
411
421
|
### Video Generation
|
|
412
422
|
| Model | Price |
|
|
@@ -441,6 +451,35 @@ const r3 = await client.generate('aerial drone shot over a snowy mountain', {
|
|
|
441
451
|
});
|
|
442
452
|
```
|
|
443
453
|
|
|
454
|
+
### Virtual Portraits
|
|
455
|
+
|
|
456
|
+
`PortraitClient` wraps `POST /v1/portrait/enroll` (paid, flat **$0.01** promo,
|
|
457
|
+
no KYC). Enroll a face image by URL and get back a Token360 asset id (`ta_xxxxxx`).
|
|
458
|
+
Pass that id as `realFaceAssetId` on a Seedance 2.0 video generation to keep the
|
|
459
|
+
same AI character across clips. Payment settles only after Token360 confirms the
|
|
460
|
+
enrollment, so a failed enrollment never charges your wallet. The returned
|
|
461
|
+
`image_url` is a gateway-mirrored copy of your source image (see `mirrored` /
|
|
462
|
+
`source_image_url`). (Real-person likeness is not supported on BlockRun —
|
|
463
|
+
enrolled portraits are AI characters.)
|
|
464
|
+
|
|
465
|
+
```ts
|
|
466
|
+
import { PortraitClient, VideoClient } from '@blockrun/llm';
|
|
467
|
+
|
|
468
|
+
const portraits = new PortraitClient();
|
|
469
|
+
const { asset_id } = await portraits.enroll({
|
|
470
|
+
name: 'Spokesperson',
|
|
471
|
+
imageUrl: 'https://example.com/face.jpg', // public https JPG/PNG/WEBP, ≤10 MB
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
// Reuse the same character across Seedance 2.0 clips
|
|
475
|
+
const video = new VideoClient();
|
|
476
|
+
const clip = await video.generate('she waves and smiles', {
|
|
477
|
+
model: 'bytedance/seedance-2.0-fast',
|
|
478
|
+
realFaceAssetId: asset_id,
|
|
479
|
+
});
|
|
480
|
+
console.log(clip.data[0].url);
|
|
481
|
+
```
|
|
482
|
+
|
|
444
483
|
### Voice Calls
|
|
445
484
|
|
|
446
485
|
`VoiceClient` wraps `POST /v1/voice/call` (paid, $0.54/call) and
|
package/dist/index.cjs
CHANGED
|
@@ -41,8 +41,10 @@ __export(index_exports, {
|
|
|
41
41
|
MusicClient: () => MusicClient,
|
|
42
42
|
OpenAI: () => OpenAI,
|
|
43
43
|
PHONE_PRICES: () => PHONE_PRICES,
|
|
44
|
+
PORTRAIT_ENROLLMENT_PRICE_USD: () => PORTRAIT_ENROLLMENT_PRICE_USD,
|
|
44
45
|
PaymentError: () => PaymentError,
|
|
45
46
|
PhoneClient: () => PhoneClient,
|
|
47
|
+
PortraitClient: () => PortraitClient,
|
|
46
48
|
PriceClient: () => PriceClient,
|
|
47
49
|
SOLANA_NETWORK: () => SOLANA_NETWORK,
|
|
48
50
|
SOLANA_WALLET_FILE_PATH: () => SOLANA_WALLET_FILE,
|
|
@@ -1461,16 +1463,18 @@ var LLMClient = class _LLMClient {
|
|
|
1461
1463
|
return data.data || [];
|
|
1462
1464
|
}
|
|
1463
1465
|
/**
|
|
1464
|
-
* Edit an image using img2img.
|
|
1466
|
+
* Edit an image using img2img, optionally fusing multiple source images.
|
|
1465
1467
|
*
|
|
1466
1468
|
* @param prompt - Text description of the desired edit
|
|
1467
|
-
* @param image -
|
|
1469
|
+
* @param image - A base64 `data:image/...` URI, or an array of 2–4 such URIs
|
|
1470
|
+
* to fuse (image fusion). Caps: `openai/*` up to 4, `google/*` up to 3.
|
|
1471
|
+
* A `mask` cannot be combined with multiple source images.
|
|
1468
1472
|
* @param options - Optional edit parameters
|
|
1469
1473
|
* @returns ImageResponse with edited image URLs
|
|
1470
1474
|
*/
|
|
1471
1475
|
async imageEdit(prompt, image, options) {
|
|
1472
1476
|
const body = {
|
|
1473
|
-
model: options?.model || "openai/gpt-image-
|
|
1477
|
+
model: options?.model || "openai/gpt-image-2",
|
|
1474
1478
|
prompt,
|
|
1475
1479
|
image,
|
|
1476
1480
|
size: options?.size || "1024x1024",
|
|
@@ -1970,20 +1974,37 @@ var ImageClient = class {
|
|
|
1970
1974
|
return this.requestWithPayment("/v1/images/generations", body);
|
|
1971
1975
|
}
|
|
1972
1976
|
/**
|
|
1973
|
-
* Edit an image using img2img.
|
|
1977
|
+
* Edit an image using img2img, optionally fusing multiple source images.
|
|
1978
|
+
*
|
|
1979
|
+
* Pass a single `data:image/...` base64 data URI to edit one image, or an
|
|
1980
|
+
* array of 2–4 data URIs to fuse them (image fusion) — e.g. a reference photo
|
|
1981
|
+
* plus a brand logo. The server caps fusion per provider: `openai/*` accepts
|
|
1982
|
+
* up to 4 source images, `google/*` (Nano Banana) up to 3. A `mask` cannot be
|
|
1983
|
+
* combined with multiple source images.
|
|
1984
|
+
*
|
|
1985
|
+
* Edit-capable models: `openai/gpt-image-1`, `openai/gpt-image-2`,
|
|
1986
|
+
* `google/nano-banana`, `google/nano-banana-pro`.
|
|
1974
1987
|
*
|
|
1975
1988
|
* @param prompt - Text description of the desired edit
|
|
1976
|
-
* @param image -
|
|
1989
|
+
* @param image - A base64 `data:image/...` URI, or an array of 2–4 such URIs to fuse
|
|
1977
1990
|
* @param options - Optional edit parameters
|
|
1978
1991
|
* @returns ImageResponse with edited image URLs
|
|
1979
1992
|
*
|
|
1980
1993
|
* @example
|
|
1981
|
-
*
|
|
1982
|
-
*
|
|
1994
|
+
* // Single-image edit
|
|
1995
|
+
* const result = await client.edit('Make it a painting', imageDataUri);
|
|
1996
|
+
*
|
|
1997
|
+
* @example
|
|
1998
|
+
* // Multi-image fusion (Nano Banana): blend a subject with a brand logo
|
|
1999
|
+
* const fused = await client.edit(
|
|
2000
|
+
* 'Place the logo on the t-shirt',
|
|
2001
|
+
* [subjectDataUri, logoDataUri],
|
|
2002
|
+
* { model: 'google/nano-banana' }
|
|
2003
|
+
* );
|
|
1983
2004
|
*/
|
|
1984
2005
|
async edit(prompt, image, options) {
|
|
1985
2006
|
const body = {
|
|
1986
|
-
model: options?.model || "openai/gpt-image-
|
|
2007
|
+
model: options?.model || "openai/gpt-image-2",
|
|
1987
2008
|
prompt,
|
|
1988
2009
|
image,
|
|
1989
2010
|
size: options?.size || "1024x1024",
|
|
@@ -2999,15 +3020,18 @@ var PhoneClient = class {
|
|
|
2999
3020
|
}
|
|
3000
3021
|
};
|
|
3001
3022
|
|
|
3002
|
-
// src/
|
|
3023
|
+
// src/portrait.ts
|
|
3003
3024
|
var import_accounts8 = require("viem/accounts");
|
|
3004
3025
|
var DEFAULT_API_URL7 = "https://blockrun.ai/api";
|
|
3005
3026
|
var DEFAULT_TIMEOUT7 = 6e4;
|
|
3006
|
-
var
|
|
3027
|
+
var PORTRAIT_ENROLLMENT_PRICE_USD = 0.01;
|
|
3028
|
+
var PortraitClient = class {
|
|
3007
3029
|
account;
|
|
3008
3030
|
privateKey;
|
|
3009
3031
|
apiUrl;
|
|
3010
3032
|
timeout;
|
|
3033
|
+
sessionTotalUsd = 0;
|
|
3034
|
+
sessionCalls = 0;
|
|
3011
3035
|
constructor(options = {}) {
|
|
3012
3036
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3013
3037
|
const privateKey = options.privateKey || envKey;
|
|
@@ -3024,6 +3048,157 @@ var SearchClient = class {
|
|
|
3024
3048
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3025
3049
|
this.timeout = options.timeout || DEFAULT_TIMEOUT7;
|
|
3026
3050
|
}
|
|
3051
|
+
/** EVM wallet address used for payments. */
|
|
3052
|
+
getWalletAddress() {
|
|
3053
|
+
return this.account.address;
|
|
3054
|
+
}
|
|
3055
|
+
/** Session-cumulative USD spend + call count across this client instance. */
|
|
3056
|
+
getSpending() {
|
|
3057
|
+
return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
|
|
3058
|
+
}
|
|
3059
|
+
/**
|
|
3060
|
+
* Enroll a Virtual Portrait from a face image URL. $0.01 (promo).
|
|
3061
|
+
*
|
|
3062
|
+
* Payment is settled only after Token360 confirms the enrollment, so failed
|
|
3063
|
+
* enrollments never charge your wallet.
|
|
3064
|
+
*
|
|
3065
|
+
* @param options.name Display name (1–64 chars).
|
|
3066
|
+
* @param options.imageUrl Public HTTPS URL to a JPG/PNG/WEBP image (≤10 MB).
|
|
3067
|
+
* @returns The enrollment record, including `asset_id` (`ta_xxxxxx`).
|
|
3068
|
+
*/
|
|
3069
|
+
async enroll(options) {
|
|
3070
|
+
const name = typeof options?.name === "string" ? options.name.trim() : "";
|
|
3071
|
+
if (name.length < 1 || name.length > 64) {
|
|
3072
|
+
throw new Error("name is required and must be 1\u201364 characters");
|
|
3073
|
+
}
|
|
3074
|
+
const imageUrl = typeof options?.imageUrl === "string" ? options.imageUrl.trim() : "";
|
|
3075
|
+
if (!/^https?:\/\//i.test(imageUrl)) {
|
|
3076
|
+
throw new Error(
|
|
3077
|
+
"imageUrl must be a public http(s) URL to a JPG/PNG/WEBP image"
|
|
3078
|
+
);
|
|
3079
|
+
}
|
|
3080
|
+
const data = await this.request({
|
|
3081
|
+
name,
|
|
3082
|
+
image_url: imageUrl
|
|
3083
|
+
});
|
|
3084
|
+
return data;
|
|
3085
|
+
}
|
|
3086
|
+
// ─── Internals ─────────────────────────────────────────────────────────
|
|
3087
|
+
async request(body) {
|
|
3088
|
+
const url = `${this.apiUrl}/v1/portrait/enroll`;
|
|
3089
|
+
const response = await this.fetchWithTimeout(url, {
|
|
3090
|
+
method: "POST",
|
|
3091
|
+
headers: { "Content-Type": "application/json" },
|
|
3092
|
+
body: JSON.stringify(body)
|
|
3093
|
+
});
|
|
3094
|
+
if (response.status === 402) {
|
|
3095
|
+
return this.handlePaymentAndRetry(url, body, response);
|
|
3096
|
+
}
|
|
3097
|
+
return this.unwrap(response, false);
|
|
3098
|
+
}
|
|
3099
|
+
async handlePaymentAndRetry(url, body, response) {
|
|
3100
|
+
let paymentHeader = response.headers.get("payment-required");
|
|
3101
|
+
if (!paymentHeader) {
|
|
3102
|
+
try {
|
|
3103
|
+
const rb = await response.json();
|
|
3104
|
+
if (rb.x402 || rb.accepts) paymentHeader = btoa(JSON.stringify(rb));
|
|
3105
|
+
} catch {
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
if (!paymentHeader) {
|
|
3109
|
+
throw new PaymentError("402 response but no payment requirements found");
|
|
3110
|
+
}
|
|
3111
|
+
const paymentRequired = parsePaymentRequired(paymentHeader);
|
|
3112
|
+
const details = extractPaymentDetails(paymentRequired);
|
|
3113
|
+
const paymentPayload = await createPaymentPayload(
|
|
3114
|
+
this.privateKey,
|
|
3115
|
+
this.account.address,
|
|
3116
|
+
details.recipient,
|
|
3117
|
+
details.amount,
|
|
3118
|
+
details.network || "eip155:8453",
|
|
3119
|
+
{
|
|
3120
|
+
resourceUrl: details.resource?.url || url,
|
|
3121
|
+
resourceDescription: details.resource?.description || "BlockRun Virtual Portrait",
|
|
3122
|
+
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
3123
|
+
extra: details.extra
|
|
3124
|
+
}
|
|
3125
|
+
);
|
|
3126
|
+
const retry = await this.fetchWithTimeout(url, {
|
|
3127
|
+
method: "POST",
|
|
3128
|
+
headers: {
|
|
3129
|
+
"Content-Type": "application/json",
|
|
3130
|
+
"PAYMENT-SIGNATURE": paymentPayload
|
|
3131
|
+
},
|
|
3132
|
+
body: JSON.stringify(body)
|
|
3133
|
+
});
|
|
3134
|
+
if (retry.status === 402) {
|
|
3135
|
+
throw new PaymentError("Payment was rejected. Check your wallet balance.");
|
|
3136
|
+
}
|
|
3137
|
+
const data = await this.unwrap(retry, true);
|
|
3138
|
+
const costUsd = Number.parseFloat(details.amount) / 1e6;
|
|
3139
|
+
this.sessionCalls += 1;
|
|
3140
|
+
this.sessionTotalUsd += costUsd;
|
|
3141
|
+
if (data && typeof data === "object" && !("txHash" in data)) {
|
|
3142
|
+
const settlement = data.settlement;
|
|
3143
|
+
if (settlement?.tx_hash) {
|
|
3144
|
+
data.txHash = settlement.tx_hash;
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
return data;
|
|
3148
|
+
}
|
|
3149
|
+
async unwrap(response, afterPayment) {
|
|
3150
|
+
if (response.ok) {
|
|
3151
|
+
return response.json();
|
|
3152
|
+
}
|
|
3153
|
+
let errorBody;
|
|
3154
|
+
try {
|
|
3155
|
+
errorBody = await response.json();
|
|
3156
|
+
} catch {
|
|
3157
|
+
errorBody = { error: "Request failed" };
|
|
3158
|
+
}
|
|
3159
|
+
const prefix = afterPayment ? "API error after payment" : "API error";
|
|
3160
|
+
throw new APIError(
|
|
3161
|
+
`${prefix}: ${response.status}`,
|
|
3162
|
+
response.status,
|
|
3163
|
+
sanitizeErrorResponse(errorBody)
|
|
3164
|
+
);
|
|
3165
|
+
}
|
|
3166
|
+
async fetchWithTimeout(url, init) {
|
|
3167
|
+
const controller = new AbortController();
|
|
3168
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
3169
|
+
try {
|
|
3170
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
3171
|
+
} finally {
|
|
3172
|
+
clearTimeout(timeoutId);
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3175
|
+
};
|
|
3176
|
+
|
|
3177
|
+
// src/search.ts
|
|
3178
|
+
var import_accounts9 = require("viem/accounts");
|
|
3179
|
+
var DEFAULT_API_URL8 = "https://blockrun.ai/api";
|
|
3180
|
+
var DEFAULT_TIMEOUT8 = 6e4;
|
|
3181
|
+
var SearchClient = class {
|
|
3182
|
+
account;
|
|
3183
|
+
privateKey;
|
|
3184
|
+
apiUrl;
|
|
3185
|
+
timeout;
|
|
3186
|
+
constructor(options = {}) {
|
|
3187
|
+
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3188
|
+
const privateKey = options.privateKey || envKey;
|
|
3189
|
+
if (!privateKey) {
|
|
3190
|
+
throw new Error(
|
|
3191
|
+
"Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
|
|
3192
|
+
);
|
|
3193
|
+
}
|
|
3194
|
+
validatePrivateKey(privateKey);
|
|
3195
|
+
this.privateKey = privateKey;
|
|
3196
|
+
this.account = (0, import_accounts9.privateKeyToAccount)(privateKey);
|
|
3197
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL8;
|
|
3198
|
+
validateApiUrl(apiUrl);
|
|
3199
|
+
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3200
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT8;
|
|
3201
|
+
}
|
|
3027
3202
|
async search(query, options) {
|
|
3028
3203
|
if (!query || query.length > 1e3) {
|
|
3029
3204
|
throw new Error("query must be 1-1000 characters");
|
|
@@ -3136,9 +3311,9 @@ var SearchClient = class {
|
|
|
3136
3311
|
};
|
|
3137
3312
|
|
|
3138
3313
|
// src/x-client.ts
|
|
3139
|
-
var
|
|
3140
|
-
var
|
|
3141
|
-
var
|
|
3314
|
+
var import_accounts10 = require("viem/accounts");
|
|
3315
|
+
var DEFAULT_API_URL9 = "https://blockrun.ai/api";
|
|
3316
|
+
var DEFAULT_TIMEOUT9 = 6e4;
|
|
3142
3317
|
var XClient = class _XClient {
|
|
3143
3318
|
account;
|
|
3144
3319
|
privateKey;
|
|
@@ -3161,11 +3336,11 @@ var XClient = class _XClient {
|
|
|
3161
3336
|
}
|
|
3162
3337
|
validatePrivateKey(privateKey);
|
|
3163
3338
|
this.privateKey = privateKey;
|
|
3164
|
-
this.account = (0,
|
|
3165
|
-
const apiUrl = options.apiUrl ||
|
|
3339
|
+
this.account = (0, import_accounts10.privateKeyToAccount)(privateKey);
|
|
3340
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL9;
|
|
3166
3341
|
validateApiUrl(apiUrl);
|
|
3167
3342
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3168
|
-
this.timeout = options.timeout ||
|
|
3343
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT9;
|
|
3169
3344
|
}
|
|
3170
3345
|
// ───────── User endpoints ─────────
|
|
3171
3346
|
userLookup(usernames) {
|
|
@@ -3343,9 +3518,9 @@ var XClient = class _XClient {
|
|
|
3343
3518
|
};
|
|
3344
3519
|
|
|
3345
3520
|
// src/price.ts
|
|
3346
|
-
var
|
|
3347
|
-
var
|
|
3348
|
-
var
|
|
3521
|
+
var import_accounts11 = require("viem/accounts");
|
|
3522
|
+
var DEFAULT_API_URL10 = "https://blockrun.ai/api";
|
|
3523
|
+
var DEFAULT_TIMEOUT10 = 3e4;
|
|
3349
3524
|
var PriceClient = class {
|
|
3350
3525
|
account = null;
|
|
3351
3526
|
privateKey = null;
|
|
@@ -3363,12 +3538,12 @@ var PriceClient = class {
|
|
|
3363
3538
|
if (privateKey) {
|
|
3364
3539
|
validatePrivateKey(privateKey);
|
|
3365
3540
|
this.privateKey = privateKey;
|
|
3366
|
-
this.account = (0,
|
|
3541
|
+
this.account = (0, import_accounts11.privateKeyToAccount)(privateKey);
|
|
3367
3542
|
}
|
|
3368
|
-
const apiUrl = options.apiUrl ||
|
|
3543
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL10;
|
|
3369
3544
|
validateApiUrl(apiUrl);
|
|
3370
3545
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3371
|
-
this.timeout = options.timeout ||
|
|
3546
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT10;
|
|
3372
3547
|
}
|
|
3373
3548
|
async price(category, symbol, options) {
|
|
3374
3549
|
if (!symbol) throw new Error("symbol is required");
|
|
@@ -3547,9 +3722,9 @@ function buildUrl(base, query) {
|
|
|
3547
3722
|
}
|
|
3548
3723
|
|
|
3549
3724
|
// src/surf.ts
|
|
3550
|
-
var
|
|
3551
|
-
var
|
|
3552
|
-
var
|
|
3725
|
+
var import_accounts12 = require("viem/accounts");
|
|
3726
|
+
var DEFAULT_API_URL11 = "https://blockrun.ai/api";
|
|
3727
|
+
var DEFAULT_TIMEOUT11 = 6e4;
|
|
3553
3728
|
var SURF_PREFIX = "/v1/surf";
|
|
3554
3729
|
var SurfClient = class {
|
|
3555
3730
|
account;
|
|
@@ -3566,11 +3741,11 @@ var SurfClient = class {
|
|
|
3566
3741
|
}
|
|
3567
3742
|
validatePrivateKey(privateKey);
|
|
3568
3743
|
this.privateKey = privateKey;
|
|
3569
|
-
this.account = (0,
|
|
3570
|
-
const apiUrl = options.apiUrl ||
|
|
3744
|
+
this.account = (0, import_accounts12.privateKeyToAccount)(privateKey);
|
|
3745
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL11;
|
|
3571
3746
|
validateApiUrl(apiUrl);
|
|
3572
3747
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3573
|
-
this.timeout = options.timeout ||
|
|
3748
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT11;
|
|
3574
3749
|
}
|
|
3575
3750
|
/**
|
|
3576
3751
|
* GET a Surf endpoint. `path` is everything after `/v1/surf` (a leading
|
|
@@ -3702,9 +3877,9 @@ var SurfClient = class {
|
|
|
3702
3877
|
};
|
|
3703
3878
|
|
|
3704
3879
|
// src/blockrun.ts
|
|
3705
|
-
var
|
|
3706
|
-
var
|
|
3707
|
-
var
|
|
3880
|
+
var import_accounts13 = require("viem/accounts");
|
|
3881
|
+
var DEFAULT_API_URL12 = "https://blockrun.ai/api";
|
|
3882
|
+
var DEFAULT_TIMEOUT12 = 6e4;
|
|
3708
3883
|
var DEFAULT_POLL_INTERVAL_MS = 5e3;
|
|
3709
3884
|
var DEFAULT_POLL_BUDGET_MS = 3e5;
|
|
3710
3885
|
var MAX_SIGNED_AUTH_SECONDS = 600;
|
|
@@ -3725,11 +3900,11 @@ var BlockrunClient = class {
|
|
|
3725
3900
|
}
|
|
3726
3901
|
validatePrivateKey(privateKey);
|
|
3727
3902
|
this.privateKey = privateKey;
|
|
3728
|
-
this.account = (0,
|
|
3729
|
-
const apiUrl = options.apiUrl ||
|
|
3903
|
+
this.account = (0, import_accounts13.privateKeyToAccount)(privateKey);
|
|
3904
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL12;
|
|
3730
3905
|
validateApiUrl(apiUrl);
|
|
3731
3906
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3732
|
-
this.timeout = options.timeout ||
|
|
3907
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT12;
|
|
3733
3908
|
}
|
|
3734
3909
|
/**
|
|
3735
3910
|
* GET a BlockRun endpoint. `path` is everything after `/api` (a leading
|
|
@@ -4080,7 +4255,7 @@ function sleep(ms) {
|
|
|
4080
4255
|
}
|
|
4081
4256
|
|
|
4082
4257
|
// src/wallet.ts
|
|
4083
|
-
var
|
|
4258
|
+
var import_accounts14 = require("viem/accounts");
|
|
4084
4259
|
var fs2 = __toESM(require("fs"), 1);
|
|
4085
4260
|
var path2 = __toESM(require("path"), 1);
|
|
4086
4261
|
var os2 = __toESM(require("os"), 1);
|
|
@@ -4089,8 +4264,8 @@ var BASE_CHAIN_ID2 = "8453";
|
|
|
4089
4264
|
var WALLET_DIR = path2.join(os2.homedir(), ".blockrun");
|
|
4090
4265
|
var WALLET_FILE = path2.join(WALLET_DIR, ".session");
|
|
4091
4266
|
function createWallet() {
|
|
4092
|
-
const privateKey = (0,
|
|
4093
|
-
const account = (0,
|
|
4267
|
+
const privateKey = (0, import_accounts14.generatePrivateKey)();
|
|
4268
|
+
const account = (0, import_accounts14.privateKeyToAccount)(privateKey);
|
|
4094
4269
|
return {
|
|
4095
4270
|
address: account.address,
|
|
4096
4271
|
privateKey
|
|
@@ -4146,12 +4321,12 @@ function loadWallet() {
|
|
|
4146
4321
|
function getOrCreateWallet() {
|
|
4147
4322
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
4148
4323
|
if (envKey) {
|
|
4149
|
-
const account = (0,
|
|
4324
|
+
const account = (0, import_accounts14.privateKeyToAccount)(envKey);
|
|
4150
4325
|
return { address: account.address, privateKey: envKey, isNew: false };
|
|
4151
4326
|
}
|
|
4152
4327
|
const fileKey = loadWallet();
|
|
4153
4328
|
if (fileKey) {
|
|
4154
|
-
const account = (0,
|
|
4329
|
+
const account = (0, import_accounts14.privateKeyToAccount)(fileKey);
|
|
4155
4330
|
return { address: account.address, privateKey: fileKey, isNew: false };
|
|
4156
4331
|
}
|
|
4157
4332
|
const { address, privateKey } = createWallet();
|
|
@@ -4161,11 +4336,11 @@ function getOrCreateWallet() {
|
|
|
4161
4336
|
function getWalletAddress() {
|
|
4162
4337
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
4163
4338
|
if (envKey) {
|
|
4164
|
-
return (0,
|
|
4339
|
+
return (0, import_accounts14.privateKeyToAccount)(envKey).address;
|
|
4165
4340
|
}
|
|
4166
4341
|
const fileKey = loadWallet();
|
|
4167
4342
|
if (fileKey) {
|
|
4168
|
-
return (0,
|
|
4343
|
+
return (0, import_accounts14.privateKeyToAccount)(fileKey).address;
|
|
4169
4344
|
}
|
|
4170
4345
|
return null;
|
|
4171
4346
|
}
|
|
@@ -4345,7 +4520,7 @@ async function getOrCreateSolanaWallet() {
|
|
|
4345
4520
|
// src/solana-client.ts
|
|
4346
4521
|
var SOLANA_API_URL = "https://sol.blockrun.ai/api";
|
|
4347
4522
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
4348
|
-
var
|
|
4523
|
+
var DEFAULT_TIMEOUT13 = 6e4;
|
|
4349
4524
|
var SDK_VERSION2 = "0.3.0";
|
|
4350
4525
|
var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
|
|
4351
4526
|
var DEFAULT_SOLANA_RPC_URL = "https://sol.blockrun.ai/api/v1/solana/rpc";
|
|
@@ -4395,7 +4570,7 @@ var SolanaLLMClient = class {
|
|
|
4395
4570
|
const rpc = resolveRpcConfig(options.rpcUrl, options.rpcHeaders);
|
|
4396
4571
|
this.rpcUrl = rpc.url;
|
|
4397
4572
|
this.rpcHeaders = rpc.headers;
|
|
4398
|
-
this.timeout = options.timeout ||
|
|
4573
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT13;
|
|
4399
4574
|
}
|
|
4400
4575
|
/** Get Solana wallet address (public key in base58). */
|
|
4401
4576
|
async getWalletAddress() {
|
|
@@ -4476,7 +4651,7 @@ var SolanaLLMClient = class {
|
|
|
4476
4651
|
/** Edit an image using img2img (Solana payment). */
|
|
4477
4652
|
async imageEdit(prompt, image, options) {
|
|
4478
4653
|
const body = {
|
|
4479
|
-
model: options?.model || "openai/gpt-image-
|
|
4654
|
+
model: options?.model || "openai/gpt-image-2",
|
|
4480
4655
|
prompt,
|
|
4481
4656
|
image,
|
|
4482
4657
|
size: options?.size || "1024x1024",
|
|
@@ -5305,7 +5480,7 @@ var OpenAI = class {
|
|
|
5305
5480
|
};
|
|
5306
5481
|
|
|
5307
5482
|
// src/anthropic-compat.ts
|
|
5308
|
-
var
|
|
5483
|
+
var import_accounts15 = require("viem/accounts");
|
|
5309
5484
|
var AnthropicClient = class {
|
|
5310
5485
|
_client = null;
|
|
5311
5486
|
_clientPromise = null;
|
|
@@ -5318,7 +5493,7 @@ var AnthropicClient = class {
|
|
|
5318
5493
|
const key = options.privateKey ?? wallet.privateKey;
|
|
5319
5494
|
validatePrivateKey(key);
|
|
5320
5495
|
this._privateKey = key;
|
|
5321
|
-
this._account = (0,
|
|
5496
|
+
this._account = (0, import_accounts15.privateKeyToAccount)(this._privateKey);
|
|
5322
5497
|
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
5323
5498
|
validateApiUrl(apiUrl);
|
|
5324
5499
|
this._apiUrl = apiUrl.replace(/\/$/, "");
|
|
@@ -5425,8 +5600,10 @@ var AnthropicClient = class {
|
|
|
5425
5600
|
MusicClient,
|
|
5426
5601
|
OpenAI,
|
|
5427
5602
|
PHONE_PRICES,
|
|
5603
|
+
PORTRAIT_ENROLLMENT_PRICE_USD,
|
|
5428
5604
|
PaymentError,
|
|
5429
5605
|
PhoneClient,
|
|
5606
|
+
PortraitClient,
|
|
5430
5607
|
PriceClient,
|
|
5431
5608
|
SOLANA_NETWORK,
|
|
5432
5609
|
SOLANA_WALLET_FILE_PATH,
|