@blockrun/llm 3.13.6 → 3.14.0

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
@@ -1,6 +1,3 @@
1
- // src/client.ts
2
- import { privateKeyToAccount } from "viem/accounts";
3
-
4
1
  // src/types.ts
5
2
  var BlockrunError = class extends Error {
6
3
  constructor(message) {
@@ -22,6 +19,8 @@ var PaymentError = class extends BlockrunError {
22
19
  };
23
20
  var APIError = class extends BlockrunError {
24
21
  statusCode;
22
+ /** Retry-After header returned by the account API. */
23
+ retryAfter;
25
24
  response;
26
25
  constructor(message, statusCode, response) {
27
26
  super(message);
@@ -31,6 +30,248 @@ var APIError = class extends BlockrunError {
31
30
  }
32
31
  };
33
32
 
33
+ // src/validation.ts
34
+ var LOCALHOST_DOMAINS = ["localhost", "127.0.0.1"];
35
+ var KNOWN_PROVIDERS = /* @__PURE__ */ new Set([
36
+ "openai",
37
+ "anthropic",
38
+ "google",
39
+ "deepseek",
40
+ "mistralai",
41
+ "meta-llama",
42
+ "together",
43
+ "xai",
44
+ "moonshot",
45
+ "nvidia",
46
+ "minimax",
47
+ "zai"
48
+ ]);
49
+ function validateModel(model) {
50
+ if (!model || typeof model !== "string") {
51
+ throw new Error("Model must be a non-empty string");
52
+ }
53
+ }
54
+ function validateMaxTokens(maxTokens) {
55
+ if (maxTokens === void 0 || maxTokens === null) {
56
+ return;
57
+ }
58
+ if (typeof maxTokens !== "number" || !Number.isInteger(maxTokens)) {
59
+ throw new Error("maxTokens must be an integer");
60
+ }
61
+ if (maxTokens < 1) {
62
+ throw new Error("maxTokens must be positive (minimum: 1)");
63
+ }
64
+ }
65
+ function validateTemperature(temperature) {
66
+ if (temperature === void 0 || temperature === null) {
67
+ return;
68
+ }
69
+ if (typeof temperature !== "number") {
70
+ throw new Error("temperature must be a number");
71
+ }
72
+ if (temperature < 0 || temperature > 2) {
73
+ throw new Error("temperature must be between 0 and 2");
74
+ }
75
+ }
76
+ function validateTopP(topP) {
77
+ if (topP === void 0 || topP === null) {
78
+ return;
79
+ }
80
+ if (typeof topP !== "number") {
81
+ throw new Error("topP must be a number");
82
+ }
83
+ if (topP < 0 || topP > 1) {
84
+ throw new Error("topP must be between 0 and 1");
85
+ }
86
+ }
87
+ function validatePrivateKey(key) {
88
+ if (typeof key !== "string") {
89
+ throw new Error("Private key must be a string");
90
+ }
91
+ if (!key.startsWith("0x")) {
92
+ throw new Error("Private key must start with 0x");
93
+ }
94
+ if (key.length !== 66) {
95
+ throw new Error(
96
+ "Private key must be 66 characters (0x + 64 hexadecimal characters)"
97
+ );
98
+ }
99
+ if (!/^0x[0-9a-fA-F]{64}$/.test(key)) {
100
+ throw new Error(
101
+ "Private key must contain only hexadecimal characters (0-9, a-f, A-F)"
102
+ );
103
+ }
104
+ }
105
+ function validateApiUrl(url) {
106
+ let parsed;
107
+ try {
108
+ parsed = new URL(url);
109
+ } catch {
110
+ throw new Error("Invalid API URL format");
111
+ }
112
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
113
+ throw new Error(
114
+ `Invalid protocol: ${parsed.protocol}. Use http:// or https://`
115
+ );
116
+ }
117
+ const isLocalhost = LOCALHOST_DOMAINS.includes(parsed.hostname);
118
+ if (parsed.protocol !== "https:" && !isLocalhost) {
119
+ throw new Error(
120
+ `API URL must use HTTPS for non-localhost endpoints. Use https:// instead of ${parsed.protocol}//`
121
+ );
122
+ }
123
+ }
124
+ function sanitizeErrorResponse(errorBody) {
125
+ if (typeof errorBody !== "object" || errorBody === null) {
126
+ return { message: "API request failed" };
127
+ }
128
+ const body = errorBody;
129
+ return {
130
+ message: typeof body.error === "string" ? body.error : "API request failed",
131
+ code: typeof body.code === "string" ? body.code : void 0
132
+ };
133
+ }
134
+ function validateResourceUrl(url, baseUrl) {
135
+ try {
136
+ const parsed = new URL(url);
137
+ const baseParsed = new URL(baseUrl);
138
+ if (parsed.hostname !== baseParsed.hostname) {
139
+ console.warn(
140
+ `Resource URL hostname mismatch: ${parsed.hostname} vs ${baseParsed.hostname}. Using safe default instead.`
141
+ );
142
+ return `${baseUrl}/v1/chat/completions`;
143
+ }
144
+ if (parsed.protocol !== baseParsed.protocol) {
145
+ console.warn(
146
+ `Resource URL protocol mismatch: ${parsed.protocol} vs ${baseParsed.protocol}. Using safe default instead.`
147
+ );
148
+ return `${baseUrl}/v1/chat/completions`;
149
+ }
150
+ return url;
151
+ } catch {
152
+ console.warn(`Invalid resource URL format: ${url}. Using safe default.`);
153
+ return `${baseUrl}/v1/chat/completions`;
154
+ }
155
+ }
156
+
157
+ // src/api-key.ts
158
+ var TRANSIENT_STATUS = /* @__PURE__ */ new Set([502, 503, 504, 522, 524]);
159
+ var TRANSIENT_RETRIES = 2;
160
+ var TRANSIENT_BACKOFF_MS = 1e3;
161
+ var API_KEY_URL = "https://api.blockrun.ai";
162
+ var PORTAL_URL = "https://user.blockrun.ai";
163
+ function resolveApiKeyAuth(options) {
164
+ if (options.apiKey !== void 0 && options.privateKey !== void 0) {
165
+ throw new Error("Pass either apiKey or privateKey, not both.");
166
+ }
167
+ const key = options.apiKey ?? (options.privateKey === void 0 && typeof process !== "undefined" ? process.env?.BLOCKRUN_API_KEY : void 0);
168
+ if (key === void 0) return void 0;
169
+ if (!/^brk_[A-Za-z0-9_-]+$/.test(key.trim())) {
170
+ throw new Error(`Invalid BlockRun API key. Create one at ${PORTAL_URL}/dashboard/keys.`);
171
+ }
172
+ const base = options.apiUrl ?? (typeof process !== "undefined" ? process.env?.BLOCKRUN_API_BASE_URL : void 0) ?? API_KEY_URL;
173
+ return new ApiKeyAuth(key.trim(), base);
174
+ }
175
+ function requireWallet(value) {
176
+ if (value === void 0) throw new Error("This operation requires a wallet; the client uses API key account billing.");
177
+ return value;
178
+ }
179
+ var ApiKeyAuth = class {
180
+ apiUrl;
181
+ #key;
182
+ constructor(key, base) {
183
+ validateApiUrl(base);
184
+ const url = new URL(base);
185
+ if (url.username || url.password || url.search || url.hash) {
186
+ throw new Error("API base URL must not contain credentials, a query, or a fragment.");
187
+ }
188
+ this.apiUrl = base.replace(/\/+$/, "").replace(/\/v1$/, "");
189
+ this.#key = key;
190
+ }
191
+ /** Resolve gateway poll paths without forwarding credentials to another origin. */
192
+ resolveUrl(path6) {
193
+ const url = new URL(path6, this.apiUrl + "/");
194
+ if (url.origin !== new URL(this.apiUrl).origin || url.username || url.password) {
195
+ throw new Error("Refusing to send a BlockRun API key to a different origin.");
196
+ }
197
+ if (new URL(this.apiUrl).pathname === "/" && url.pathname.startsWith("/api/v1/")) url.pathname = url.pathname.slice(4);
198
+ return url.href;
199
+ }
200
+ async fetch(input, init, raiseErrors = true) {
201
+ const request = input instanceof Request ? input : void 0;
202
+ const url = this.resolveUrl(request?.url ?? String(input));
203
+ const headers = new Headers(init?.headers ?? request?.headers);
204
+ for (const name of [...headers.keys()]) {
205
+ if (name.toLowerCase().includes("payment") || name.toLowerCase() === "x-api-key") headers.delete(name);
206
+ }
207
+ headers.set("authorization", `Bearer ${this.#key}`);
208
+ const method = (init?.method ?? request?.method ?? "GET").toUpperCase();
209
+ const retries = method === "GET" || method === "HEAD" ? TRANSIENT_RETRIES : 0;
210
+ let response;
211
+ for (let attempt = 0; ; attempt++) {
212
+ response = await globalThis.fetch(request ? new Request(url, request) : url, {
213
+ ...init,
214
+ headers,
215
+ redirect: "error"
216
+ });
217
+ if (attempt >= retries || !TRANSIENT_STATUS.has(response.status)) break;
218
+ await new Promise((resolve) => setTimeout(resolve, TRANSIENT_BACKOFF_MS * (attempt + 1)));
219
+ }
220
+ if (raiseErrors && !response.ok) {
221
+ let body;
222
+ try {
223
+ body = await response.json();
224
+ } catch {
225
+ body = void 0;
226
+ }
227
+ const outer = body && typeof body === "object" ? body : {};
228
+ const detail = outer.error && typeof outer.error === "object" ? outer.error : outer;
229
+ const safe = Object.fromEntries(["message", "code", "type", "param"].flatMap((name) => typeof detail[name] === "string" ? [[name, detail[name].split(this.#key).join("[REDACTED]")]] : []));
230
+ const hint = response.status === 402 ? ` Top up at ${PORTAL_URL}/dashboard/credits.` : response.status === 401 ? ` Check your key at ${PORTAL_URL}/dashboard/keys.` : "";
231
+ const error = new APIError(`BlockRun account API error: ${response.status}.${hint}`, response.status, safe);
232
+ error.retryAfter = response.headers.get("retry-after") ?? void 0;
233
+ throw error;
234
+ }
235
+ return response;
236
+ }
237
+ /** Poll an account-owned async job without ever entering the x402 signing path. */
238
+ async poll(response, timeout, interval) {
239
+ const deadline = Date.now() + timeout;
240
+ let data = await response.json();
241
+ if (["failed", "cancelled", "canceled"].includes(String(data.status))) {
242
+ throw new APIError("Account API job failed or was cancelled", 502);
243
+ }
244
+ const pollPath = data.poll_url;
245
+ if (typeof pollPath !== "string") {
246
+ if (response.status === 202 || ["queued", "in_progress", "processing"].includes(String(data.status))) {
247
+ throw new APIError("Async response missing poll_url", response.status);
248
+ }
249
+ return data;
250
+ }
251
+ const url = this.resolveUrl(pollPath);
252
+ while (Date.now() < deadline) {
253
+ if (data.status === "completed") return data;
254
+ if (["failed", "cancelled", "canceled"].includes(String(data.status))) {
255
+ throw new APIError("Account API job failed or was cancelled", 502, sanitizeErrorResponse(data));
256
+ }
257
+ await new Promise((resolve) => setTimeout(resolve, Math.min(interval, Math.max(0, deadline - Date.now()))));
258
+ const remaining = deadline - Date.now();
259
+ if (remaining <= 0) break;
260
+ try {
261
+ const res = await this.fetch(url, { signal: AbortSignal.timeout(remaining) });
262
+ data = await res.json();
263
+ } catch (err) {
264
+ if (!(err instanceof APIError) || !TRANSIENT_STATUS.has(err.statusCode)) throw err;
265
+ }
266
+ }
267
+ if (data.status === "completed") return data;
268
+ throw new APIError("Account API job polling timed out; check the job before submitting again.", 504, { poll_url: url });
269
+ }
270
+ };
271
+
272
+ // src/client.ts
273
+ import { privateKeyToAccount } from "viem/accounts";
274
+
34
275
  // node_modules/.pnpm/@blockrun+router-core@https+++codeload.github.com+BlockRunAI+router-core+tar.gz+814fd3b6bc788_xq5fkcckbb2p7dtp6dodey4yri/node_modules/@blockrun/router-core/dist/index.js
35
276
  function scoreTokenCount(estimatedTokens, thresholds) {
36
277
  if (estimatedTokens < thresholds.simple) {
@@ -4161,9 +4402,11 @@ function parsePaymentRequired(headerValue) {
4161
4402
  if (error.message.includes("Invalid payment required structure")) {
4162
4403
  throw error;
4163
4404
  }
4164
- throw new Error("Failed to parse payment required header: invalid format");
4405
+ throw new Error("Failed to parse payment required header: invalid format", {
4406
+ cause: error
4407
+ });
4165
4408
  }
4166
- throw new Error("Failed to parse payment required header");
4409
+ throw new Error("Failed to parse payment required header", { cause: error });
4167
4410
  }
4168
4411
  }
4169
4412
  function extractPaymentDetails(paymentRequired, preferredNetwork) {
@@ -4194,130 +4437,6 @@ function extractPaymentDetails(paymentRequired, preferredNetwork) {
4194
4437
  };
4195
4438
  }
4196
4439
 
4197
- // src/validation.ts
4198
- var LOCALHOST_DOMAINS = ["localhost", "127.0.0.1"];
4199
- var KNOWN_PROVIDERS = /* @__PURE__ */ new Set([
4200
- "openai",
4201
- "anthropic",
4202
- "google",
4203
- "deepseek",
4204
- "mistralai",
4205
- "meta-llama",
4206
- "together",
4207
- "xai",
4208
- "moonshot",
4209
- "nvidia",
4210
- "minimax",
4211
- "zai"
4212
- ]);
4213
- function validateModel(model) {
4214
- if (!model || typeof model !== "string") {
4215
- throw new Error("Model must be a non-empty string");
4216
- }
4217
- }
4218
- function validateMaxTokens(maxTokens) {
4219
- if (maxTokens === void 0 || maxTokens === null) {
4220
- return;
4221
- }
4222
- if (typeof maxTokens !== "number" || !Number.isInteger(maxTokens)) {
4223
- throw new Error("maxTokens must be an integer");
4224
- }
4225
- if (maxTokens < 1) {
4226
- throw new Error("maxTokens must be positive (minimum: 1)");
4227
- }
4228
- }
4229
- function validateTemperature(temperature) {
4230
- if (temperature === void 0 || temperature === null) {
4231
- return;
4232
- }
4233
- if (typeof temperature !== "number") {
4234
- throw new Error("temperature must be a number");
4235
- }
4236
- if (temperature < 0 || temperature > 2) {
4237
- throw new Error("temperature must be between 0 and 2");
4238
- }
4239
- }
4240
- function validateTopP(topP) {
4241
- if (topP === void 0 || topP === null) {
4242
- return;
4243
- }
4244
- if (typeof topP !== "number") {
4245
- throw new Error("topP must be a number");
4246
- }
4247
- if (topP < 0 || topP > 1) {
4248
- throw new Error("topP must be between 0 and 1");
4249
- }
4250
- }
4251
- function validatePrivateKey(key) {
4252
- if (typeof key !== "string") {
4253
- throw new Error("Private key must be a string");
4254
- }
4255
- if (!key.startsWith("0x")) {
4256
- throw new Error("Private key must start with 0x");
4257
- }
4258
- if (key.length !== 66) {
4259
- throw new Error(
4260
- "Private key must be 66 characters (0x + 64 hexadecimal characters)"
4261
- );
4262
- }
4263
- if (!/^0x[0-9a-fA-F]{64}$/.test(key)) {
4264
- throw new Error(
4265
- "Private key must contain only hexadecimal characters (0-9, a-f, A-F)"
4266
- );
4267
- }
4268
- }
4269
- function validateApiUrl(url) {
4270
- let parsed;
4271
- try {
4272
- parsed = new URL(url);
4273
- } catch {
4274
- throw new Error("Invalid API URL format");
4275
- }
4276
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
4277
- throw new Error(
4278
- `Invalid protocol: ${parsed.protocol}. Use http:// or https://`
4279
- );
4280
- }
4281
- const isLocalhost = LOCALHOST_DOMAINS.includes(parsed.hostname);
4282
- if (parsed.protocol !== "https:" && !isLocalhost) {
4283
- throw new Error(
4284
- `API URL must use HTTPS for non-localhost endpoints. Use https:// instead of ${parsed.protocol}//`
4285
- );
4286
- }
4287
- }
4288
- function sanitizeErrorResponse(errorBody) {
4289
- if (typeof errorBody !== "object" || errorBody === null) {
4290
- return { message: "API request failed" };
4291
- }
4292
- const body = errorBody;
4293
- return {
4294
- message: typeof body.error === "string" ? body.error : "API request failed",
4295
- code: typeof body.code === "string" ? body.code : void 0
4296
- };
4297
- }
4298
- function validateResourceUrl(url, baseUrl) {
4299
- try {
4300
- const parsed = new URL(url);
4301
- const baseParsed = new URL(baseUrl);
4302
- if (parsed.hostname !== baseParsed.hostname) {
4303
- console.warn(
4304
- `Resource URL hostname mismatch: ${parsed.hostname} vs ${baseParsed.hostname}. Using safe default instead.`
4305
- );
4306
- return `${baseUrl}/v1/chat/completions`;
4307
- }
4308
- if (parsed.protocol !== baseParsed.protocol) {
4309
- console.warn(
4310
- `Resource URL protocol mismatch: ${parsed.protocol} vs ${baseParsed.protocol}. Using safe default instead.`
4311
- );
4312
- return `${baseUrl}/v1/chat/completions`;
4313
- }
4314
- return url;
4315
- } catch {
4316
- console.warn(`Invalid resource URL format: ${url}. Using safe default.`);
4317
- return `${baseUrl}/v1/chat/completions`;
4318
- }
4319
- }
4320
-
4321
4440
  // src/cost-log.ts
4322
4441
  import * as fs from "fs";
4323
4442
  import * as path from "path";
@@ -4364,7 +4483,7 @@ function getCostSummary() {
4364
4483
  }
4365
4484
 
4366
4485
  // src/version.ts
4367
- var SDK_VERSION = "3.13.6";
4486
+ var SDK_VERSION = "3.14.0";
4368
4487
  var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
4369
4488
 
4370
4489
  // src/client.ts
@@ -4412,8 +4531,19 @@ function resolveDefaultTimeout() {
4412
4531
  var DEFAULT_TIMEOUT = resolveDefaultTimeout();
4413
4532
  var LLMClient = class _LLMClient {
4414
4533
  static DEFAULT_API_URL = DEFAULT_API_URL;
4415
- account;
4416
- privateKey;
4534
+ _account;
4535
+ get account() {
4536
+ return requireWallet(this._account);
4537
+ }
4538
+ apiAuth;
4539
+ /** Active billing mode. */
4540
+ get authMode() {
4541
+ return this.apiAuth ? "api-key" : "wallet";
4542
+ }
4543
+ _privateKey;
4544
+ get privateKey() {
4545
+ return requireWallet(this._privateKey);
4546
+ }
4417
4547
  apiUrl;
4418
4548
  timeout;
4419
4549
  sessionTotalUsd = 0;
@@ -4431,17 +4561,20 @@ var LLMClient = class _LLMClient {
4431
4561
  * @param options - Client configuration options (optional if BASE_CHAIN_WALLET_KEY env var is set)
4432
4562
  */
4433
4563
  constructor(options = {}) {
4434
- const envKey = typeof process !== "undefined" && process.env ? process.env.BASE_CHAIN_WALLET_KEY : void 0;
4435
- const privateKey = options.privateKey || envKey;
4436
- if (!privateKey) {
4437
- throw new Error(
4438
- "Private key required. Pass privateKey in options or set BASE_CHAIN_WALLET_KEY environment variable."
4439
- );
4564
+ this.apiAuth = resolveApiKeyAuth(options);
4565
+ if (!this.apiAuth) {
4566
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BASE_CHAIN_WALLET_KEY : void 0;
4567
+ const privateKey = options.privateKey || envKey;
4568
+ if (!privateKey) {
4569
+ throw new Error(
4570
+ "Private key required. Pass privateKey in options or set BASE_CHAIN_WALLET_KEY environment variable."
4571
+ );
4572
+ }
4573
+ validatePrivateKey(privateKey);
4574
+ this._privateKey = privateKey;
4575
+ this._account = privateKeyToAccount(privateKey);
4440
4576
  }
4441
- validatePrivateKey(privateKey);
4442
- this.privateKey = privateKey;
4443
- this.account = privateKeyToAccount(privateKey);
4444
- const apiUrl = options.apiUrl || DEFAULT_API_URL;
4577
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL;
4445
4578
  validateApiUrl(apiUrl);
4446
4579
  this.apiUrl = apiUrl.replace(/\/$/, "");
4447
4580
  this.timeout = options.timeout || DEFAULT_TIMEOUT;
@@ -4482,7 +4615,7 @@ var LLMClient = class _LLMClient {
4482
4615
  systemPrompt,
4483
4616
  maxOutputTokens,
4484
4617
  await this.getModelPricing(),
4485
- { ...options, minimumPaymentUsd: BASE_MINIMUM_PAYMENT_USD }
4618
+ { ...options, minimumPaymentUsd: this.apiAuth ? 0 : BASE_MINIMUM_PAYMENT_USD }
4486
4619
  );
4487
4620
  }
4488
4621
  /**
@@ -5068,6 +5201,7 @@ var LLMClient = class _LLMClient {
5068
5201
  sanitizeErrorResponse(errorBody)
5069
5202
  );
5070
5203
  }
5204
+ if (this.apiAuth && endpoint.startsWith("/v1/images/")) return this.apiAuth.poll(response, this.timeout, 2e3);
5071
5205
  return response.json();
5072
5206
  }
5073
5207
  /**
@@ -5320,7 +5454,7 @@ var LLMClient = class _LLMClient {
5320
5454
  const controller = new AbortController();
5321
5455
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
5322
5456
  try {
5323
- const response = await fetch(url, {
5457
+ const response = await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, {
5324
5458
  ...options,
5325
5459
  signal: controller.signal
5326
5460
  });
@@ -5821,6 +5955,7 @@ var LLMClient = class _LLMClient {
5821
5955
  * console.log(`Spent $${spending.totalUsd.toFixed(4)} across ${spending.calls} calls`);
5822
5956
  */
5823
5957
  getSpending() {
5958
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
5824
5959
  return {
5825
5960
  totalUsd: this.sessionTotalUsd,
5826
5961
  calls: this.sessionCalls
@@ -5844,8 +5979,19 @@ var DEFAULT_TIMEOUT2 = 2e5;
5844
5979
  var POLL_INTERVAL_MS = 3e3;
5845
5980
  var POLL_MAX_DURATION_MS = 3e5;
5846
5981
  var ImageClient = class {
5847
- account;
5848
- privateKey;
5982
+ _account;
5983
+ get account() {
5984
+ return requireWallet(this._account);
5985
+ }
5986
+ apiAuth;
5987
+ /** Active billing mode. */
5988
+ get authMode() {
5989
+ return this.apiAuth ? "api-key" : "wallet";
5990
+ }
5991
+ _privateKey;
5992
+ get privateKey() {
5993
+ return requireWallet(this._privateKey);
5994
+ }
5849
5995
  apiUrl;
5850
5996
  timeout;
5851
5997
  sessionTotalUsd = 0;
@@ -5856,17 +6002,20 @@ var ImageClient = class {
5856
6002
  * @param options - Client configuration options
5857
6003
  */
5858
6004
  constructor(options = {}) {
5859
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
5860
- const privateKey = options.privateKey || envKey;
5861
- if (!privateKey) {
5862
- throw new Error(
5863
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
5864
- );
6005
+ this.apiAuth = resolveApiKeyAuth(options);
6006
+ if (!this.apiAuth) {
6007
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
6008
+ const privateKey = options.privateKey || envKey;
6009
+ if (!privateKey) {
6010
+ throw new Error(
6011
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
6012
+ );
6013
+ }
6014
+ validatePrivateKey(privateKey);
6015
+ this._privateKey = privateKey;
6016
+ this._account = privateKeyToAccount2(privateKey);
5865
6017
  }
5866
- validatePrivateKey(privateKey);
5867
- this.privateKey = privateKey;
5868
- this.account = privateKeyToAccount2(privateKey);
5869
- const apiUrl = options.apiUrl || DEFAULT_API_URL2;
6018
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL2;
5870
6019
  validateApiUrl(apiUrl);
5871
6020
  this.apiUrl = apiUrl.replace(/\/$/, "");
5872
6021
  this.timeout = options.timeout || DEFAULT_TIMEOUT2;
@@ -5993,6 +6142,7 @@ var ImageClient = class {
5993
6142
  sanitizeErrorResponse(errorBody)
5994
6143
  );
5995
6144
  }
6145
+ if (this.apiAuth) return this.apiAuth.poll(response, POLL_MAX_DURATION_MS, POLL_INTERVAL_MS);
5996
6146
  return response.json();
5997
6147
  }
5998
6148
  /**
@@ -6130,7 +6280,7 @@ var ImageClient = class {
6130
6280
  const controller = new AbortController();
6131
6281
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
6132
6282
  try {
6133
- const response = await fetch(url, {
6283
+ const response = await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, {
6134
6284
  ...options,
6135
6285
  signal: controller.signal
6136
6286
  });
@@ -6149,6 +6299,7 @@ var ImageClient = class {
6149
6299
  * Get session spending information.
6150
6300
  */
6151
6301
  getSpending() {
6302
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
6152
6303
  return {
6153
6304
  totalUsd: this.sessionTotalUsd,
6154
6305
  calls: this.sessionCalls
@@ -6162,24 +6313,38 @@ var DEFAULT_API_URL3 = "https://blockrun.ai/api";
6162
6313
  var DEFAULT_MODEL2 = "minimax/music-2.5+";
6163
6314
  var DEFAULT_TIMEOUT3 = 21e4;
6164
6315
  var MusicClient = class {
6165
- account;
6166
- privateKey;
6316
+ _account;
6317
+ get account() {
6318
+ return requireWallet(this._account);
6319
+ }
6320
+ apiAuth;
6321
+ /** Active billing mode. */
6322
+ get authMode() {
6323
+ return this.apiAuth ? "api-key" : "wallet";
6324
+ }
6325
+ _privateKey;
6326
+ get privateKey() {
6327
+ return requireWallet(this._privateKey);
6328
+ }
6167
6329
  apiUrl;
6168
6330
  timeout;
6169
6331
  sessionTotalUsd = 0;
6170
6332
  sessionCalls = 0;
6171
6333
  constructor(options = {}) {
6172
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
6173
- const privateKey = options.privateKey || envKey;
6174
- if (!privateKey) {
6175
- throw new Error(
6176
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
6177
- );
6334
+ this.apiAuth = resolveApiKeyAuth(options);
6335
+ if (!this.apiAuth) {
6336
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
6337
+ const privateKey = options.privateKey || envKey;
6338
+ if (!privateKey) {
6339
+ throw new Error(
6340
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
6341
+ );
6342
+ }
6343
+ validatePrivateKey(privateKey);
6344
+ this._privateKey = privateKey;
6345
+ this._account = privateKeyToAccount3(privateKey);
6178
6346
  }
6179
- validatePrivateKey(privateKey);
6180
- this.privateKey = privateKey;
6181
- this.account = privateKeyToAccount3(privateKey);
6182
- const apiUrl = options.apiUrl || DEFAULT_API_URL3;
6347
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL3;
6183
6348
  validateApiUrl(apiUrl);
6184
6349
  this.apiUrl = apiUrl.replace(/\/$/, "");
6185
6350
  this.timeout = options.timeout || DEFAULT_TIMEOUT3;
@@ -6236,6 +6401,7 @@ var MusicClient = class {
6236
6401
  }
6237
6402
  throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
6238
6403
  }
6404
+ if (this.apiAuth) return this.apiAuth.poll(response, this.timeout, 5e3);
6239
6405
  return response.json();
6240
6406
  }
6241
6407
  async handlePaymentAndRetry(url, body, response) {
@@ -6298,7 +6464,7 @@ var MusicClient = class {
6298
6464
  const controller = new AbortController();
6299
6465
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
6300
6466
  try {
6301
- return await fetch(url, { ...options, signal: controller.signal });
6467
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...options, signal: controller.signal });
6302
6468
  } finally {
6303
6469
  clearTimeout(timeoutId);
6304
6470
  }
@@ -6307,6 +6473,7 @@ var MusicClient = class {
6307
6473
  return this.account.address;
6308
6474
  }
6309
6475
  getSpending() {
6476
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
6310
6477
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
6311
6478
  }
6312
6479
  };
@@ -6318,24 +6485,38 @@ var DEFAULT_MODEL3 = "elevenlabs/flash-v2.5";
6318
6485
  var DEFAULT_SOUNDFX_MODEL = "elevenlabs/sound-effects";
6319
6486
  var DEFAULT_TIMEOUT4 = 12e4;
6320
6487
  var SpeechClient = class {
6321
- account;
6322
- privateKey;
6488
+ _account;
6489
+ get account() {
6490
+ return requireWallet(this._account);
6491
+ }
6492
+ apiAuth;
6493
+ /** Active billing mode. */
6494
+ get authMode() {
6495
+ return this.apiAuth ? "api-key" : "wallet";
6496
+ }
6497
+ _privateKey;
6498
+ get privateKey() {
6499
+ return requireWallet(this._privateKey);
6500
+ }
6323
6501
  apiUrl;
6324
6502
  timeout;
6325
6503
  sessionTotalUsd = 0;
6326
6504
  sessionCalls = 0;
6327
6505
  constructor(options = {}) {
6328
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
6329
- const privateKey = options.privateKey || envKey;
6330
- if (!privateKey) {
6331
- throw new Error(
6332
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
6333
- );
6506
+ this.apiAuth = resolveApiKeyAuth(options);
6507
+ if (!this.apiAuth) {
6508
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
6509
+ const privateKey = options.privateKey || envKey;
6510
+ if (!privateKey) {
6511
+ throw new Error(
6512
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
6513
+ );
6514
+ }
6515
+ validatePrivateKey(privateKey);
6516
+ this._privateKey = privateKey;
6517
+ this._account = privateKeyToAccount4(privateKey);
6334
6518
  }
6335
- validatePrivateKey(privateKey);
6336
- this.privateKey = privateKey;
6337
- this.account = privateKeyToAccount4(privateKey);
6338
- const apiUrl = options.apiUrl || DEFAULT_API_URL4;
6519
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL4;
6339
6520
  validateApiUrl(apiUrl);
6340
6521
  this.apiUrl = apiUrl.replace(/\/$/, "");
6341
6522
  this.timeout = options.timeout || DEFAULT_TIMEOUT4;
@@ -6497,7 +6678,7 @@ var SpeechClient = class {
6497
6678
  const controller = new AbortController();
6498
6679
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
6499
6680
  try {
6500
- return await fetch(url, { ...options, signal: controller.signal });
6681
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...options, signal: controller.signal });
6501
6682
  } finally {
6502
6683
  clearTimeout(timeoutId);
6503
6684
  }
@@ -6506,6 +6687,7 @@ var SpeechClient = class {
6506
6687
  return this.account.address;
6507
6688
  }
6508
6689
  getSpending() {
6690
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
6509
6691
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
6510
6692
  }
6511
6693
  };
@@ -6520,24 +6702,38 @@ var DEFAULT_GENERATE_BUDGET_MS = 9e5;
6520
6702
  var MAX_TIMEOUT_SECONDS = 600;
6521
6703
  var MAX_POLL_RESIGNS = 2;
6522
6704
  var VideoClient = class {
6523
- account;
6524
- privateKey;
6705
+ _account;
6706
+ get account() {
6707
+ return requireWallet(this._account);
6708
+ }
6709
+ apiAuth;
6710
+ /** Active billing mode. */
6711
+ get authMode() {
6712
+ return this.apiAuth ? "api-key" : "wallet";
6713
+ }
6714
+ _privateKey;
6715
+ get privateKey() {
6716
+ return requireWallet(this._privateKey);
6717
+ }
6525
6718
  apiUrl;
6526
6719
  timeout;
6527
6720
  sessionTotalUsd = 0;
6528
6721
  sessionCalls = 0;
6529
6722
  constructor(options = {}) {
6530
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
6531
- const privateKey = options.privateKey || envKey;
6532
- if (!privateKey) {
6533
- throw new Error(
6534
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
6535
- );
6723
+ this.apiAuth = resolveApiKeyAuth(options);
6724
+ if (!this.apiAuth) {
6725
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
6726
+ const privateKey = options.privateKey || envKey;
6727
+ if (!privateKey) {
6728
+ throw new Error(
6729
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
6730
+ );
6731
+ }
6732
+ validatePrivateKey(privateKey);
6733
+ this._privateKey = privateKey;
6734
+ this._account = privateKeyToAccount5(privateKey);
6536
6735
  }
6537
- validatePrivateKey(privateKey);
6538
- this.privateKey = privateKey;
6539
- this.account = privateKeyToAccount5(privateKey);
6540
- const apiUrl = options.apiUrl || DEFAULT_API_URL5;
6736
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL5;
6541
6737
  validateApiUrl(apiUrl);
6542
6738
  this.apiUrl = apiUrl.replace(/\/$/, "");
6543
6739
  this.timeout = options.timeout || DEFAULT_TIMEOUT5;
@@ -6663,6 +6859,7 @@ var VideoClient = class {
6663
6859
  headers: { "Content-Type": "application/json" },
6664
6860
  body: JSON.stringify(body)
6665
6861
  });
6862
+ if (this.apiAuth) return this.apiAuth.poll(resp402, budgetMs, POLL_INTERVAL_MS2);
6666
6863
  if (resp402.status !== 402) {
6667
6864
  await this.throwApiError(resp402, "Expected 402 on first POST");
6668
6865
  }
@@ -6810,7 +7007,7 @@ var VideoClient = class {
6810
7007
  const controller = new AbortController();
6811
7008
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
6812
7009
  try {
6813
- return await fetch(url, { ...options, signal: controller.signal });
7010
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...options, signal: controller.signal });
6814
7011
  } finally {
6815
7012
  clearTimeout(timeoutId);
6816
7013
  }
@@ -6819,6 +7016,7 @@ var VideoClient = class {
6819
7016
  return this.account.address;
6820
7017
  }
6821
7018
  getSpending() {
7019
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
6822
7020
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
6823
7021
  }
6824
7022
  };
@@ -6830,24 +7028,38 @@ var DEFAULT_TIMEOUT6 = 6e4;
6830
7028
  var CALL_PRICE_USD = 0.54;
6831
7029
  var VALID_MODELS = /* @__PURE__ */ new Set(["base", "enhanced", "turbo"]);
6832
7030
  var VoiceClient = class {
6833
- account;
6834
- privateKey;
7031
+ _account;
7032
+ get account() {
7033
+ return requireWallet(this._account);
7034
+ }
7035
+ apiAuth;
7036
+ /** Active billing mode. */
7037
+ get authMode() {
7038
+ return this.apiAuth ? "api-key" : "wallet";
7039
+ }
7040
+ _privateKey;
7041
+ get privateKey() {
7042
+ return requireWallet(this._privateKey);
7043
+ }
6835
7044
  apiUrl;
6836
7045
  timeout;
6837
7046
  sessionTotalUsd = 0;
6838
7047
  sessionCalls = 0;
6839
7048
  constructor(options = {}) {
6840
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
6841
- const privateKey = options.privateKey || envKey;
6842
- if (!privateKey) {
6843
- throw new Error(
6844
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
6845
- );
7049
+ this.apiAuth = resolveApiKeyAuth(options);
7050
+ if (!this.apiAuth) {
7051
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7052
+ const privateKey = options.privateKey || envKey;
7053
+ if (!privateKey) {
7054
+ throw new Error(
7055
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
7056
+ );
7057
+ }
7058
+ validatePrivateKey(privateKey);
7059
+ this._privateKey = privateKey;
7060
+ this._account = privateKeyToAccount6(privateKey);
6846
7061
  }
6847
- validatePrivateKey(privateKey);
6848
- this.privateKey = privateKey;
6849
- this.account = privateKeyToAccount6(privateKey);
6850
- const apiUrl = options.apiUrl || DEFAULT_API_URL6;
7062
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL6;
6851
7063
  validateApiUrl(apiUrl);
6852
7064
  this.apiUrl = apiUrl.replace(/\/$/, "");
6853
7065
  this.timeout = options.timeout || DEFAULT_TIMEOUT6;
@@ -7011,7 +7223,7 @@ var VoiceClient = class {
7011
7223
  const controller = new AbortController();
7012
7224
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
7013
7225
  try {
7014
- return await fetch(url, { ...options, signal: controller.signal });
7226
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...options, signal: controller.signal });
7015
7227
  } finally {
7016
7228
  clearTimeout(timeoutId);
7017
7229
  }
@@ -7020,6 +7232,7 @@ var VoiceClient = class {
7020
7232
  return this.account.address;
7021
7233
  }
7022
7234
  getSpending() {
7235
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
7023
7236
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
7024
7237
  }
7025
7238
  };
@@ -7049,24 +7262,38 @@ function requireE164(value) {
7049
7262
  return v;
7050
7263
  }
7051
7264
  var PhoneClient = class {
7052
- account;
7053
- privateKey;
7265
+ _account;
7266
+ get account() {
7267
+ return requireWallet(this._account);
7268
+ }
7269
+ apiAuth;
7270
+ /** Active billing mode. */
7271
+ get authMode() {
7272
+ return this.apiAuth ? "api-key" : "wallet";
7273
+ }
7274
+ _privateKey;
7275
+ get privateKey() {
7276
+ return requireWallet(this._privateKey);
7277
+ }
7054
7278
  apiUrl;
7055
7279
  timeout;
7056
7280
  sessionTotalUsd = 0;
7057
7281
  sessionCalls = 0;
7058
7282
  constructor(options = {}) {
7059
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7060
- const privateKey = options.privateKey || envKey;
7061
- if (!privateKey) {
7062
- throw new Error(
7063
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
7064
- );
7283
+ this.apiAuth = resolveApiKeyAuth(options);
7284
+ if (!this.apiAuth) {
7285
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7286
+ const privateKey = options.privateKey || envKey;
7287
+ if (!privateKey) {
7288
+ throw new Error(
7289
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
7290
+ );
7291
+ }
7292
+ validatePrivateKey(privateKey);
7293
+ this._privateKey = privateKey;
7294
+ this._account = privateKeyToAccount7(privateKey);
7065
7295
  }
7066
- validatePrivateKey(privateKey);
7067
- this.privateKey = privateKey;
7068
- this.account = privateKeyToAccount7(privateKey);
7069
- const apiUrl = options.apiUrl || DEFAULT_API_URL7;
7296
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL7;
7070
7297
  validateApiUrl(apiUrl);
7071
7298
  this.apiUrl = apiUrl.replace(/\/$/, "");
7072
7299
  this.timeout = options.timeout || DEFAULT_TIMEOUT7;
@@ -7077,6 +7304,7 @@ var PhoneClient = class {
7077
7304
  }
7078
7305
  /** Session-cumulative USD spend + call count across this client instance. */
7079
7306
  getSpending() {
7307
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
7080
7308
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
7081
7309
  }
7082
7310
  // ─── Lookup ────────────────────────────────────────────────────────────
@@ -7236,7 +7464,7 @@ var PhoneClient = class {
7236
7464
  const controller = new AbortController();
7237
7465
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
7238
7466
  try {
7239
- return await fetch(url, { ...init, signal: controller.signal });
7467
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...init, signal: controller.signal });
7240
7468
  } finally {
7241
7469
  clearTimeout(timeoutId);
7242
7470
  }
@@ -7249,24 +7477,38 @@ var DEFAULT_API_URL8 = "https://blockrun.ai/api";
7249
7477
  var DEFAULT_TIMEOUT8 = 6e4;
7250
7478
  var PORTRAIT_ENROLLMENT_PRICE_USD = 0.01;
7251
7479
  var PortraitClient = class {
7252
- account;
7253
- privateKey;
7480
+ _account;
7481
+ get account() {
7482
+ return requireWallet(this._account);
7483
+ }
7484
+ apiAuth;
7485
+ /** Active billing mode. */
7486
+ get authMode() {
7487
+ return this.apiAuth ? "api-key" : "wallet";
7488
+ }
7489
+ _privateKey;
7490
+ get privateKey() {
7491
+ return requireWallet(this._privateKey);
7492
+ }
7254
7493
  apiUrl;
7255
7494
  timeout;
7256
7495
  sessionTotalUsd = 0;
7257
7496
  sessionCalls = 0;
7258
7497
  constructor(options = {}) {
7259
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7260
- const privateKey = options.privateKey || envKey;
7261
- if (!privateKey) {
7262
- throw new Error(
7263
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
7264
- );
7498
+ this.apiAuth = resolveApiKeyAuth(options);
7499
+ if (!this.apiAuth) {
7500
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7501
+ const privateKey = options.privateKey || envKey;
7502
+ if (!privateKey) {
7503
+ throw new Error(
7504
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
7505
+ );
7506
+ }
7507
+ validatePrivateKey(privateKey);
7508
+ this._privateKey = privateKey;
7509
+ this._account = privateKeyToAccount8(privateKey);
7265
7510
  }
7266
- validatePrivateKey(privateKey);
7267
- this.privateKey = privateKey;
7268
- this.account = privateKeyToAccount8(privateKey);
7269
- const apiUrl = options.apiUrl || DEFAULT_API_URL8;
7511
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL8;
7270
7512
  validateApiUrl(apiUrl);
7271
7513
  this.apiUrl = apiUrl.replace(/\/$/, "");
7272
7514
  this.timeout = options.timeout || DEFAULT_TIMEOUT8;
@@ -7277,6 +7519,7 @@ var PortraitClient = class {
7277
7519
  }
7278
7520
  /** Session-cumulative USD spend + call count across this client instance. */
7279
7521
  getSpending() {
7522
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
7280
7523
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
7281
7524
  }
7282
7525
  /**
@@ -7390,7 +7633,7 @@ var PortraitClient = class {
7390
7633
  const controller = new AbortController();
7391
7634
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
7392
7635
  try {
7393
- return await fetch(url, { ...init, signal: controller.signal });
7636
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...init, signal: controller.signal });
7394
7637
  } finally {
7395
7638
  clearTimeout(timeoutId);
7396
7639
  }
@@ -7402,22 +7645,36 @@ import { privateKeyToAccount as privateKeyToAccount9 } from "viem/accounts";
7402
7645
  var DEFAULT_API_URL9 = "https://blockrun.ai/api";
7403
7646
  var DEFAULT_TIMEOUT9 = 6e4;
7404
7647
  var SearchClient = class {
7405
- account;
7406
- privateKey;
7648
+ _account;
7649
+ get account() {
7650
+ return requireWallet(this._account);
7651
+ }
7652
+ apiAuth;
7653
+ /** Active billing mode. */
7654
+ get authMode() {
7655
+ return this.apiAuth ? "api-key" : "wallet";
7656
+ }
7657
+ _privateKey;
7658
+ get privateKey() {
7659
+ return requireWallet(this._privateKey);
7660
+ }
7407
7661
  apiUrl;
7408
7662
  timeout;
7409
7663
  constructor(options = {}) {
7410
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7411
- const privateKey = options.privateKey || envKey;
7412
- if (!privateKey) {
7413
- throw new Error(
7414
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
7415
- );
7664
+ this.apiAuth = resolveApiKeyAuth(options);
7665
+ if (!this.apiAuth) {
7666
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7667
+ const privateKey = options.privateKey || envKey;
7668
+ if (!privateKey) {
7669
+ throw new Error(
7670
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
7671
+ );
7672
+ }
7673
+ validatePrivateKey(privateKey);
7674
+ this._privateKey = privateKey;
7675
+ this._account = privateKeyToAccount9(privateKey);
7416
7676
  }
7417
- validatePrivateKey(privateKey);
7418
- this.privateKey = privateKey;
7419
- this.account = privateKeyToAccount9(privateKey);
7420
- const apiUrl = options.apiUrl || DEFAULT_API_URL9;
7677
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL9;
7421
7678
  validateApiUrl(apiUrl);
7422
7679
  this.apiUrl = apiUrl.replace(/\/$/, "");
7423
7680
  this.timeout = options.timeout || DEFAULT_TIMEOUT9;
@@ -7523,7 +7780,7 @@ var SearchClient = class {
7523
7780
  const controller = new AbortController();
7524
7781
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
7525
7782
  try {
7526
- return await fetch(url, { ...init, signal: controller.signal });
7783
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...init, signal: controller.signal });
7527
7784
  } finally {
7528
7785
  clearTimeout(timeoutId);
7529
7786
  }
@@ -7538,15 +7795,20 @@ import { privateKeyToAccount as privateKeyToAccount10 } from "viem/accounts";
7538
7795
  var DEFAULT_API_URL10 = "https://blockrun.ai/api";
7539
7796
  var DEFAULT_TIMEOUT10 = 3e4;
7540
7797
  var PriceClient = class {
7798
+ apiAuth;
7799
+ get authMode() {
7800
+ return this.apiAuth ? "api-key" : "wallet";
7801
+ }
7541
7802
  account = null;
7542
7803
  privateKey = null;
7543
7804
  apiUrl;
7544
7805
  timeout;
7545
7806
  constructor(options = {}) {
7807
+ this.apiAuth = resolveApiKeyAuth(options);
7546
7808
  const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7547
- const privateKey = options.privateKey || envKey;
7548
- const requireWallet = options.requireWallet ?? true;
7549
- if (!privateKey && requireWallet) {
7809
+ const privateKey = this.apiAuth ? void 0 : options.privateKey || envKey;
7810
+ const requireWallet2 = options.requireWallet ?? true;
7811
+ if (!this.apiAuth && !privateKey && requireWallet2) {
7550
7812
  throw new Error(
7551
7813
  "Private key required for paid endpoints. Pass privateKey in options, set BLOCKRUN_WALLET_KEY, or pass requireWallet: false for free-only usage."
7552
7814
  );
@@ -7556,7 +7818,7 @@ var PriceClient = class {
7556
7818
  this.privateKey = privateKey;
7557
7819
  this.account = privateKeyToAccount10(privateKey);
7558
7820
  }
7559
- const apiUrl = options.apiUrl || DEFAULT_API_URL10;
7821
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL10;
7560
7822
  validateApiUrl(apiUrl);
7561
7823
  this.apiUrl = apiUrl.replace(/\/$/, "");
7562
7824
  this.timeout = options.timeout || DEFAULT_TIMEOUT10;
@@ -7709,7 +7971,7 @@ var PriceClient = class {
7709
7971
  const controller = new AbortController();
7710
7972
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
7711
7973
  try {
7712
- return await fetch(url, { ...init, signal: controller.signal });
7974
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...init, signal: controller.signal });
7713
7975
  } finally {
7714
7976
  clearTimeout(timeoutId);
7715
7977
  }
@@ -7743,22 +8005,36 @@ var DEFAULT_API_URL11 = "https://blockrun.ai/api";
7743
8005
  var DEFAULT_TIMEOUT11 = 6e4;
7744
8006
  var SURF_PREFIX = "/v1/surf";
7745
8007
  var SurfClient = class {
7746
- account;
7747
- privateKey;
8008
+ _account;
8009
+ get account() {
8010
+ return requireWallet(this._account);
8011
+ }
8012
+ apiAuth;
8013
+ /** Active billing mode. */
8014
+ get authMode() {
8015
+ return this.apiAuth ? "api-key" : "wallet";
8016
+ }
8017
+ _privateKey;
8018
+ get privateKey() {
8019
+ return requireWallet(this._privateKey);
8020
+ }
7748
8021
  apiUrl;
7749
8022
  timeout;
7750
8023
  constructor(options = {}) {
7751
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7752
- const privateKey = options.privateKey || envKey;
7753
- if (!privateKey) {
7754
- throw new Error(
7755
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
7756
- );
8024
+ this.apiAuth = resolveApiKeyAuth(options);
8025
+ if (!this.apiAuth) {
8026
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
8027
+ const privateKey = options.privateKey || envKey;
8028
+ if (!privateKey) {
8029
+ throw new Error(
8030
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
8031
+ );
8032
+ }
8033
+ validatePrivateKey(privateKey);
8034
+ this._privateKey = privateKey;
8035
+ this._account = privateKeyToAccount11(privateKey);
7757
8036
  }
7758
- validatePrivateKey(privateKey);
7759
- this.privateKey = privateKey;
7760
- this.account = privateKeyToAccount11(privateKey);
7761
- const apiUrl = options.apiUrl || DEFAULT_API_URL11;
8037
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL11;
7762
8038
  validateApiUrl(apiUrl);
7763
8039
  this.apiUrl = apiUrl.replace(/\/$/, "");
7764
8040
  this.timeout = options.timeout || DEFAULT_TIMEOUT11;
@@ -7882,7 +8158,7 @@ var SurfClient = class {
7882
8158
  const controller = new AbortController();
7883
8159
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
7884
8160
  try {
7885
- return await fetch(url, { ...init, signal: controller.signal });
8161
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...init, signal: controller.signal });
7886
8162
  } finally {
7887
8163
  clearTimeout(timeoutId);
7888
8164
  }
@@ -7971,24 +8247,38 @@ var NETWORK_ALIASES = {
7971
8247
  zec: "zcash"
7972
8248
  };
7973
8249
  var RpcClient = class {
7974
- account;
7975
- privateKey;
8250
+ _account;
8251
+ get account() {
8252
+ return requireWallet(this._account);
8253
+ }
8254
+ apiAuth;
8255
+ /** Active billing mode. */
8256
+ get authMode() {
8257
+ return this.apiAuth ? "api-key" : "wallet";
8258
+ }
8259
+ _privateKey;
8260
+ get privateKey() {
8261
+ return requireWallet(this._privateKey);
8262
+ }
7976
8263
  apiUrl;
7977
8264
  timeout;
7978
8265
  sessionTotalUsd = 0;
7979
8266
  sessionCalls = 0;
7980
8267
  constructor(options = {}) {
7981
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
7982
- const privateKey = options.privateKey || envKey;
7983
- if (!privateKey) {
7984
- throw new Error(
7985
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
7986
- );
8268
+ this.apiAuth = resolveApiKeyAuth(options);
8269
+ if (!this.apiAuth) {
8270
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
8271
+ const privateKey = options.privateKey || envKey;
8272
+ if (!privateKey) {
8273
+ throw new Error(
8274
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
8275
+ );
8276
+ }
8277
+ validatePrivateKey(privateKey);
8278
+ this._privateKey = privateKey;
8279
+ this._account = privateKeyToAccount12(privateKey);
7987
8280
  }
7988
- validatePrivateKey(privateKey);
7989
- this.privateKey = privateKey;
7990
- this.account = privateKeyToAccount12(privateKey);
7991
- const apiUrl = options.apiUrl || DEFAULT_API_URL12;
8281
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL12;
7992
8282
  validateApiUrl(apiUrl);
7993
8283
  this.apiUrl = apiUrl.replace(/\/$/, "");
7994
8284
  this.timeout = options.timeout || DEFAULT_TIMEOUT12;
@@ -8132,7 +8422,7 @@ var RpcClient = class {
8132
8422
  const controller = new AbortController();
8133
8423
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
8134
8424
  try {
8135
- return await fetch(url, { ...options, signal: controller.signal });
8425
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...options, signal: controller.signal });
8136
8426
  } finally {
8137
8427
  clearTimeout(timeoutId);
8138
8428
  }
@@ -8141,6 +8431,7 @@ var RpcClient = class {
8141
8431
  return this.account.address;
8142
8432
  }
8143
8433
  getSpending() {
8434
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
8144
8435
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
8145
8436
  }
8146
8437
  };
@@ -8153,24 +8444,38 @@ var DEFAULT_POLL_INTERVAL_MS = 5e3;
8153
8444
  var DEFAULT_POLL_BUDGET_MS = 3e5;
8154
8445
  var MAX_SIGNED_AUTH_SECONDS = 600;
8155
8446
  var BlockrunClient = class {
8156
- account;
8157
- privateKey;
8447
+ _account;
8448
+ get account() {
8449
+ return requireWallet(this._account);
8450
+ }
8451
+ apiAuth;
8452
+ /** Active billing mode. */
8453
+ get authMode() {
8454
+ return this.apiAuth ? "api-key" : "wallet";
8455
+ }
8456
+ _privateKey;
8457
+ get privateKey() {
8458
+ return requireWallet(this._privateKey);
8459
+ }
8158
8460
  apiUrl;
8159
8461
  timeout;
8160
8462
  sessionTotalUsd = 0;
8161
8463
  sessionCalls = 0;
8162
8464
  constructor(options = {}) {
8163
- const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
8164
- const privateKey = options.privateKey || envKey;
8165
- if (!privateKey) {
8166
- throw new Error(
8167
- "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
8168
- );
8465
+ this.apiAuth = resolveApiKeyAuth(options);
8466
+ if (!this.apiAuth) {
8467
+ const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
8468
+ const privateKey = options.privateKey || envKey;
8469
+ if (!privateKey) {
8470
+ throw new Error(
8471
+ "Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
8472
+ );
8473
+ }
8474
+ validatePrivateKey(privateKey);
8475
+ this._privateKey = privateKey;
8476
+ this._account = privateKeyToAccount13(privateKey);
8169
8477
  }
8170
- validatePrivateKey(privateKey);
8171
- this.privateKey = privateKey;
8172
- this.account = privateKeyToAccount13(privateKey);
8173
- const apiUrl = options.apiUrl || DEFAULT_API_URL13;
8478
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || DEFAULT_API_URL13;
8174
8479
  validateApiUrl(apiUrl);
8175
8480
  this.apiUrl = apiUrl.replace(/\/$/, "");
8176
8481
  this.timeout = options.timeout || DEFAULT_TIMEOUT13;
@@ -8212,6 +8517,7 @@ var BlockrunClient = class {
8212
8517
  headers: { "Content-Type": "application/json" },
8213
8518
  body: JSON.stringify(body ?? {})
8214
8519
  });
8520
+ if (this.apiAuth) return this.apiAuth.poll(resp402, budgetMs, intervalMs);
8215
8521
  if (resp402.status === 200) {
8216
8522
  return resp402.json();
8217
8523
  }
@@ -8504,7 +8810,7 @@ var BlockrunClient = class {
8504
8810
  const controller = new AbortController();
8505
8811
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
8506
8812
  try {
8507
- return await fetch(url, { ...init, signal: controller.signal });
8813
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...init, signal: controller.signal });
8508
8814
  } finally {
8509
8815
  clearTimeout(timeoutId);
8510
8816
  }
@@ -8516,6 +8822,7 @@ var BlockrunClient = class {
8516
8822
  return this.account.address;
8517
8823
  }
8518
8824
  getSpending() {
8825
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
8519
8826
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
8520
8827
  }
8521
8828
  };
@@ -8526,7 +8833,7 @@ function sleep(ms) {
8526
8833
  // src/wallet.ts
8527
8834
  import { privateKeyToAccount as privateKeyToAccount15, generatePrivateKey as generatePrivateKey2 } from "viem/accounts";
8528
8835
 
8529
- // node_modules/.pnpm/@blockrun+core@0.1.1_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@3.25.76/node_modules/@blockrun/core/dist/config.js
8836
+ // node_modules/.pnpm/@blockrun+core@0.1.1_bufferutil@4.1.0_typescript@6.0.3_utf-8-validate@6.0.6_zod@3.25.76/node_modules/@blockrun/core/dist/config.js
8530
8837
  import * as fs2 from "fs";
8531
8838
  import * as os2 from "os";
8532
8839
  import * as path2 from "path";
@@ -8548,7 +8855,7 @@ function paths() {
8548
8855
  };
8549
8856
  }
8550
8857
 
8551
- // node_modules/.pnpm/@blockrun+core@0.1.1_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@3.25.76/node_modules/@blockrun/core/dist/wallet.js
8858
+ // node_modules/.pnpm/@blockrun+core@0.1.1_bufferutil@4.1.0_typescript@6.0.3_utf-8-validate@6.0.6_zod@3.25.76/node_modules/@blockrun/core/dist/wallet.js
8552
8859
  import * as fs3 from "fs";
8553
8860
  import * as path3 from "path";
8554
8861
  import { privateKeyToAccount as privateKeyToAccount14, generatePrivateKey } from "viem/accounts";
@@ -8844,7 +9151,8 @@ async function solanaKeyToBytes(privateKey) {
8844
9151
  } catch (err) {
8845
9152
  const msg = err instanceof Error ? err.message : String(err);
8846
9153
  throw new Error(
8847
- `Invalid Solana private key: ${msg}. Expected a base58-encoded 64-byte key (standard Solana format), a 64-byte hex string, or a Solana CLI JSON byte array.`
9154
+ `Invalid Solana private key: ${msg}. Expected a base58-encoded 64-byte key (standard Solana format), a 64-byte hex string, or a Solana CLI JSON byte array.`,
9155
+ { cause: err }
8848
9156
  );
8849
9157
  }
8850
9158
  }
@@ -8990,7 +9298,7 @@ async function solanaPublicKeyFrom(privateKey, source) {
8990
9298
  return await solanaPublicKey(privateKey);
8991
9299
  } catch (err) {
8992
9300
  const msg = err instanceof Error ? err.message : String(err);
8993
- throw new Error(`${msg} (key loaded from ${source})`);
9301
+ throw new Error(`${msg} (key loaded from ${source})`, { cause: err });
8994
9302
  }
8995
9303
  }
8996
9304
  async function getOrCreateSolanaWallet() {
@@ -9104,7 +9412,14 @@ function resolveRpcConfig(rpcUrl, rpcHeaders) {
9104
9412
  }
9105
9413
  var SolanaLLMClient = class {
9106
9414
  static SOLANA_API_URL = SOLANA_API_URL;
9107
- privateKey;
9415
+ apiAuth;
9416
+ get authMode() {
9417
+ return this.apiAuth ? "api-key" : "wallet";
9418
+ }
9419
+ _privateKey;
9420
+ get privateKey() {
9421
+ return requireWallet(this._privateKey);
9422
+ }
9108
9423
  apiUrl;
9109
9424
  rpcUrl;
9110
9425
  rpcHeaders;
@@ -9115,15 +9430,18 @@ var SolanaLLMClient = class {
9115
9430
  modelPricingCache = null;
9116
9431
  modelPricingPromise = null;
9117
9432
  constructor(options = {}) {
9118
- const envKey = typeof process !== "undefined" && process.env ? process.env.SOLANA_WALLET_KEY : void 0;
9119
- const privateKey = options.privateKey || envKey;
9120
- if (!privateKey) {
9121
- throw new Error(
9122
- "Private key required. Pass privateKey in options or set SOLANA_WALLET_KEY environment variable."
9123
- );
9433
+ this.apiAuth = resolveApiKeyAuth(options);
9434
+ if (!this.apiAuth) {
9435
+ const envKey = typeof process !== "undefined" && process.env ? process.env.SOLANA_WALLET_KEY : void 0;
9436
+ const privateKey = options.privateKey || envKey;
9437
+ if (!privateKey) {
9438
+ throw new Error(
9439
+ "Private key required. Pass privateKey in options or set SOLANA_WALLET_KEY environment variable."
9440
+ );
9441
+ }
9442
+ this._privateKey = privateKey;
9124
9443
  }
9125
- this.privateKey = privateKey;
9126
- const apiUrl = options.apiUrl || SOLANA_API_URL;
9444
+ const apiUrl = this.apiAuth?.apiUrl || options.apiUrl || SOLANA_API_URL;
9127
9445
  validateApiUrl(apiUrl);
9128
9446
  this.apiUrl = apiUrl.replace(/\/$/, "");
9129
9447
  const rpc = resolveRpcConfig(options.rpcUrl, options.rpcHeaders);
@@ -9236,7 +9554,7 @@ var SolanaLLMClient = class {
9236
9554
  {
9237
9555
  routingProfile: options?.routingProfile,
9238
9556
  requiresStructuredOutput: options?.responseFormat !== void 0,
9239
- minimumPaymentUsd: SOLANA_MINIMUM_PAYMENT_USD
9557
+ minimumPaymentUsd: this.apiAuth ? 0 : SOLANA_MINIMUM_PAYMENT_USD
9240
9558
  }
9241
9559
  );
9242
9560
  }
@@ -9265,7 +9583,7 @@ var SolanaLLMClient = class {
9265
9583
  toolChoice: options.toolChoice,
9266
9584
  conversationChars,
9267
9585
  hasVision,
9268
- minimumPaymentUsd: SOLANA_MINIMUM_PAYMENT_USD
9586
+ minimumPaymentUsd: this.apiAuth ? 0 : SOLANA_MINIMUM_PAYMENT_USD
9269
9587
  }
9270
9588
  );
9271
9589
  const response = await this.chatCompletion(decision.model, messages, {
@@ -9518,6 +9836,7 @@ var SolanaLLMClient = class {
9518
9836
  }
9519
9837
  /** Get session spending. */
9520
9838
  getSpending() {
9839
+ if (this.apiAuth) throw new Error("Account usage is available at https://user.blockrun.ai/dashboard; getSpending() tracks x402 settlements only.");
9521
9840
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
9522
9841
  }
9523
9842
  /** True if using sol.blockrun.ai. */
@@ -9654,6 +9973,7 @@ var SolanaLLMClient = class {
9654
9973
  }
9655
9974
  throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
9656
9975
  }
9976
+ if (this.apiAuth && endpoint.startsWith("/v1/images/")) return this.apiAuth.poll(response, this.timeout, 2e3);
9657
9977
  return response.json();
9658
9978
  }
9659
9979
  }
@@ -9840,7 +10160,7 @@ var SolanaLLMClient = class {
9840
10160
  const controller = new AbortController();
9841
10161
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
9842
10162
  try {
9843
- return await fetch(url, { ...options, signal: controller.signal });
10163
+ return await (this.apiAuth ? this.apiAuth.fetch.bind(this.apiAuth) : fetch)(url, { ...options, signal: controller.signal });
9844
10164
  } finally {
9845
10165
  clearTimeout(timeoutId);
9846
10166
  }
@@ -10039,6 +10359,9 @@ function getCostLogSummary() {
10039
10359
  }
10040
10360
 
10041
10361
  // src/setup.ts
10362
+ import { readFileSync as readFileSync6 } from "fs";
10363
+ import { homedir as homedir5 } from "os";
10364
+ import { join as join6 } from "path";
10042
10365
  function setupAgentWallet(options) {
10043
10366
  const { address, privateKey, isNew } = getOrCreateWallet();
10044
10367
  if (isNew) {
@@ -10081,6 +10404,24 @@ async function status() {
10081
10404
  console.log(`Balance: $${balance.toFixed(2)} USDC`);
10082
10405
  return { address, balance };
10083
10406
  }
10407
+ async function setupAgentClient(options = {}) {
10408
+ if (resolveApiKeyAuth(options)) return new LLMClient({ apiKey: options.apiKey });
10409
+ let chain = options.chain;
10410
+ if (!chain) {
10411
+ for (const file of ["payment-chain", ".chain"]) {
10412
+ try {
10413
+ const saved = readFileSync6(join6(homedir5(), ".blockrun", file), "utf8").trim();
10414
+ if (saved === "solana" || saved === "base") {
10415
+ chain = saved;
10416
+ break;
10417
+ }
10418
+ } catch {
10419
+ }
10420
+ }
10421
+ }
10422
+ chain ??= !loadSolanaWallet() && loadWallet() ? "base" : "solana";
10423
+ return chain === "solana" ? setupAgentSolanaWallet(options) : setupAgentWallet(options);
10424
+ }
10084
10425
 
10085
10426
  // src/openai-compat.ts
10086
10427
  var StreamingResponse = class {
@@ -10212,13 +10553,17 @@ var Chat = class {
10212
10553
  };
10213
10554
  var OpenAI = class {
10214
10555
  chat;
10556
+ get authMode() {
10557
+ return this.client.authMode;
10558
+ }
10215
10559
  client;
10216
10560
  constructor(options = {}) {
10217
10561
  const privateKey = options.walletKey || options.privateKey;
10218
- const apiUrl = options.baseURL || "https://blockrun.ai/api";
10562
+ const apiUrl = resolveApiKeyAuth({ apiKey: options.apiKey, privateKey, apiUrl: options.baseURL })?.apiUrl ?? options.baseURL ?? "https://blockrun.ai/api";
10219
10563
  const timeout = options.timeout ?? DEFAULT_TIMEOUT;
10220
10564
  this.client = new LLMClient({
10221
10565
  privateKey,
10566
+ apiKey: options.apiKey,
10222
10567
  apiUrl,
10223
10568
  timeout
10224
10569
  });
@@ -10237,17 +10582,29 @@ import { privateKeyToAccount as privateKeyToAccount16 } from "viem/accounts";
10237
10582
  var AnthropicClient = class {
10238
10583
  _client = null;
10239
10584
  _clientPromise = null;
10240
- _privateKey;
10241
- _account;
10585
+ apiAuth;
10586
+ get authMode() {
10587
+ return this.apiAuth ? "api-key" : "wallet";
10588
+ }
10589
+ walletKey;
10590
+ get _privateKey() {
10591
+ return requireWallet(this.walletKey);
10592
+ }
10593
+ walletAccount;
10594
+ get _account() {
10595
+ return requireWallet(this.walletAccount);
10596
+ }
10242
10597
  _apiUrl;
10243
10598
  _timeout;
10244
10599
  constructor(options = {}) {
10245
- const wallet = getOrCreateWallet();
10246
- const key = options.privateKey ?? wallet.privateKey;
10247
- validatePrivateKey(key);
10248
- this._privateKey = key;
10249
- this._account = privateKeyToAccount16(this._privateKey);
10250
- const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
10600
+ this.apiAuth = resolveApiKeyAuth(options);
10601
+ if (!this.apiAuth) {
10602
+ const key = options.privateKey ?? getOrCreateWallet().privateKey;
10603
+ validatePrivateKey(key);
10604
+ this.walletKey = key;
10605
+ this.walletAccount = privateKeyToAccount16(this.walletKey);
10606
+ }
10607
+ const apiUrl = this.apiAuth?.apiUrl ?? options.apiUrl ?? "https://blockrun.ai/api";
10251
10608
  validateApiUrl(apiUrl);
10252
10609
  this._apiUrl = apiUrl.replace(/\/$/, "");
10253
10610
  this._timeout = options.timeout ?? DEFAULT_TIMEOUT;
@@ -10271,6 +10628,7 @@ var AnthropicClient = class {
10271
10628
  const timeoutId = setTimeout(() => controller.abort(), this._timeout);
10272
10629
  try {
10273
10630
  const mergedInit = { ...init, signal: controller.signal };
10631
+ if (this.apiAuth) return await this.apiAuth.fetch(input, mergedInit, false);
10274
10632
  let response = await globalThis.fetch(input, mergedInit);
10275
10633
  if (response.status === 402) {
10276
10634
  let paymentHeader = response.headers.get("payment-required");
@@ -10342,6 +10700,7 @@ var AnthropicClient = class {
10342
10700
  };
10343
10701
  export {
10344
10702
  APIError,
10703
+ API_KEY_URL,
10345
10704
  AnthropicClient,
10346
10705
  BASE_CHAIN_ID,
10347
10706
  BlockrunClient,
@@ -10353,6 +10712,7 @@ export {
10353
10712
  NETWORK_ALIASES,
10354
10713
  OpenAI,
10355
10714
  PHONE_PRICES,
10715
+ PORTAL_URL,
10356
10716
  PORTRAIT_ENROLLMENT_PRICE_USD,
10357
10717
  PaymentError,
10358
10718
  PhoneClient,
@@ -10410,6 +10770,7 @@ export {
10410
10770
  scanSolanaWallets,
10411
10771
  scanWallets2 as scanWallets,
10412
10772
  setCache,
10773
+ setupAgentClient,
10413
10774
  setupAgentSolanaWallet,
10414
10775
  setupAgentWallet,
10415
10776
  solanaClient,