@blockrun/llm 0.2.0 → 0.3.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.cjs CHANGED
@@ -51,7 +51,8 @@ __export(index_exports, {
51
51
  getPaymentLinks: () => getPaymentLinks,
52
52
  getWalletAddress: () => getWalletAddress,
53
53
  loadWallet: () => loadWallet,
54
- saveWallet: () => saveWallet
54
+ saveWallet: () => saveWallet,
55
+ testnetClient: () => testnetClient
55
56
  });
56
57
  module.exports = __toCommonJS(index_exports);
57
58
 
@@ -278,9 +279,14 @@ function validateResourceUrl(url, baseUrl) {
278
279
 
279
280
  // src/client.ts
280
281
  var DEFAULT_API_URL = "https://blockrun.ai/api";
282
+ var TESTNET_API_URL = "https://testnet.blockrun.ai/api";
281
283
  var DEFAULT_MAX_TOKENS = 1024;
282
284
  var DEFAULT_TIMEOUT = 6e4;
285
+ var SDK_VERSION = "0.3.0";
286
+ var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
283
287
  var LLMClient = class {
288
+ static DEFAULT_API_URL = DEFAULT_API_URL;
289
+ static TESTNET_API_URL = TESTNET_API_URL;
284
290
  account;
285
291
  privateKey;
286
292
  apiUrl;
@@ -333,7 +339,7 @@ var LLMClient = class {
333
339
  search: options?.search,
334
340
  searchParameters: options?.searchParameters
335
341
  });
336
- return result.choices[0].message.content;
342
+ return result.choices[0].message.content || "";
337
343
  }
338
344
  /**
339
345
  * Full chat completion interface (OpenAI-compatible).
@@ -360,6 +366,12 @@ var LLMClient = class {
360
366
  } else if (options?.search === true) {
361
367
  body.search_parameters = { mode: "on" };
362
368
  }
369
+ if (options?.tools !== void 0) {
370
+ body.tools = options.tools;
371
+ }
372
+ if (options?.toolChoice !== void 0) {
373
+ body.tool_choice = options.toolChoice;
374
+ }
363
375
  return this.requestWithPayment("/v1/chat/completions", body);
364
376
  }
365
377
  /**
@@ -369,7 +381,7 @@ var LLMClient = class {
369
381
  const url = `${this.apiUrl}${endpoint}`;
370
382
  const response = await this.fetchWithTimeout(url, {
371
383
  method: "POST",
372
- headers: { "Content-Type": "application/json" },
384
+ headers: { "Content-Type": "application/json", "User-Agent": USER_AGENT },
373
385
  body: JSON.stringify(body)
374
386
  });
375
387
  if (response.status === 402) {
@@ -432,6 +444,7 @@ var LLMClient = class {
432
444
  method: "POST",
433
445
  headers: {
434
446
  "Content-Type": "application/json",
447
+ "User-Agent": USER_AGENT,
435
448
  "PAYMENT-SIGNATURE": paymentPayload
436
449
  },
437
450
  body: JSON.stringify(body)
@@ -560,7 +573,19 @@ var LLMClient = class {
560
573
  getWalletAddress() {
561
574
  return this.account.address;
562
575
  }
576
+ /**
577
+ * Check if client is configured for testnet.
578
+ */
579
+ isTestnet() {
580
+ return this.apiUrl.includes("testnet.blockrun.ai");
581
+ }
563
582
  };
583
+ function testnetClient(options = {}) {
584
+ return new LLMClient({
585
+ ...options,
586
+ apiUrl: TESTNET_API_URL
587
+ });
588
+ }
564
589
  var client_default = LLMClient;
565
590
 
566
591
  // src/image.ts
@@ -962,7 +987,9 @@ var ChatCompletions = class {
962
987
  {
963
988
  maxTokens: params.max_tokens,
964
989
  temperature: params.temperature,
965
- topP: params.top_p
990
+ topP: params.top_p,
991
+ tools: params.tools,
992
+ toolChoice: params.tool_choice
966
993
  }
967
994
  );
968
995
  return this.transformResponse(response);
@@ -977,6 +1004,12 @@ var ChatCompletions = class {
977
1004
  top_p: params.top_p,
978
1005
  stream: true
979
1006
  };
1007
+ if (params.tools) {
1008
+ body.tools = params.tools;
1009
+ }
1010
+ if (params.tool_choice) {
1011
+ body.tool_choice = params.tool_choice;
1012
+ }
980
1013
  const controller = new AbortController();
981
1014
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
982
1015
  try {
@@ -1013,7 +1046,8 @@ var ChatCompletions = class {
1013
1046
  index: choice.index ?? index,
1014
1047
  message: {
1015
1048
  role: "assistant",
1016
- content: choice.message.content
1049
+ content: choice.message.content,
1050
+ tool_calls: choice.message.tool_calls
1017
1051
  },
1018
1052
  finish_reason: choice.finish_reason || "stop"
1019
1053
  })),
@@ -1070,5 +1104,6 @@ var OpenAI = class {
1070
1104
  getPaymentLinks,
1071
1105
  getWalletAddress,
1072
1106
  loadWallet,
1073
- saveWallet
1107
+ saveWallet,
1108
+ testnetClient
1074
1109
  });
package/dist/index.d.cts CHANGED
@@ -1,14 +1,42 @@
1
1
  /**
2
2
  * Type definitions for BlockRun LLM SDK
3
3
  */
4
+ interface FunctionDefinition {
5
+ name: string;
6
+ description?: string;
7
+ parameters?: Record<string, unknown>;
8
+ strict?: boolean;
9
+ }
10
+ interface Tool {
11
+ type: "function";
12
+ function: FunctionDefinition;
13
+ }
14
+ interface FunctionCall {
15
+ name: string;
16
+ arguments: string;
17
+ }
18
+ interface ToolCall {
19
+ id: string;
20
+ type: "function";
21
+ function: FunctionCall;
22
+ }
23
+ type ToolChoice = "none" | "auto" | "required" | {
24
+ type: "function";
25
+ function: {
26
+ name: string;
27
+ };
28
+ };
4
29
  interface ChatMessage {
5
- role: "system" | "user" | "assistant";
6
- content: string;
30
+ role: "system" | "user" | "assistant" | "tool";
31
+ content?: string | null;
32
+ name?: string;
33
+ tool_call_id?: string;
34
+ tool_calls?: ToolCall[];
7
35
  }
8
36
  interface ChatChoice {
9
37
  index: number;
10
38
  message: ChatMessage;
11
- finish_reason?: string;
39
+ finish_reason?: "stop" | "length" | "content_filter" | "tool_calls";
12
40
  }
13
41
  interface ChatUsage {
14
42
  prompt_tokens: number;
@@ -146,6 +174,10 @@ interface ChatCompletionOptions {
146
174
  search?: boolean;
147
175
  /** Full xAI Live Search configuration (for Grok models) */
148
176
  searchParameters?: SearchParameters;
177
+ /** Tool definitions for function calling */
178
+ tools?: Tool[];
179
+ /** Tool selection strategy */
180
+ toolChoice?: ToolChoice;
149
181
  }
150
182
  declare class BlockrunError extends Error {
151
183
  constructor(message: string);
@@ -180,8 +212,28 @@ declare class APIError extends BlockrunError {
180
212
  *
181
213
  * Provides access to multiple LLM providers (OpenAI, Anthropic, Google, etc.)
182
214
  * with automatic x402 micropayments on Base chain.
215
+ *
216
+ * Networks:
217
+ * - Mainnet: https://blockrun.ai/api (Base, Chain ID 8453)
218
+ * - Testnet: https://testnet.blockrun.ai/api (Base Sepolia, Chain ID 84532)
219
+ *
220
+ * @example Testnet usage
221
+ * ```ts
222
+ * // Use testnet convenience function
223
+ * import { testnetClient } from '@blockrun/llm';
224
+ * const client = testnetClient({ privateKey: '0x...' });
225
+ * const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
226
+ *
227
+ * // Or configure manually
228
+ * const client = new LLMClient({
229
+ * privateKey: '0x...',
230
+ * apiUrl: 'https://testnet.blockrun.ai/api'
231
+ * });
232
+ * ```
183
233
  */
184
234
  declare class LLMClient {
235
+ static readonly DEFAULT_API_URL = "https://blockrun.ai/api";
236
+ static readonly TESTNET_API_URL = "https://testnet.blockrun.ai/api";
185
237
  private account;
186
238
  private privateKey;
187
239
  private apiUrl;
@@ -266,7 +318,38 @@ declare class LLMClient {
266
318
  * Get the wallet address being used for payments.
267
319
  */
268
320
  getWalletAddress(): string;
321
+ /**
322
+ * Check if client is configured for testnet.
323
+ */
324
+ isTestnet(): boolean;
269
325
  }
326
+ /**
327
+ * Create a testnet LLM client for development and testing.
328
+ *
329
+ * This is a convenience function that creates an LLMClient configured
330
+ * for the BlockRun testnet (Base Sepolia).
331
+ *
332
+ * @param options - Client options (privateKey required unless BASE_CHAIN_WALLET_KEY env var is set)
333
+ * @returns LLMClient configured for testnet
334
+ *
335
+ * @example
336
+ * ```ts
337
+ * import { testnetClient } from '@blockrun/llm';
338
+ *
339
+ * const client = testnetClient({ privateKey: '0x...' });
340
+ * const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
341
+ * ```
342
+ *
343
+ * Testnet Setup:
344
+ * 1. Get testnet ETH from https://www.alchemy.com/faucets/base-sepolia
345
+ * 2. Get testnet USDC from https://faucet.circle.com/
346
+ * 3. Use your wallet with testnet funds
347
+ *
348
+ * Available Testnet Models:
349
+ * - openai/gpt-oss-20b
350
+ * - openai/gpt-oss-120b
351
+ */
352
+ declare function testnetClient(options?: Omit<LLMClientOptions, 'apiUrl'>): LLMClient;
270
353
 
271
354
  /**
272
355
  * BlockRun Image Client - Generate images via x402 micropayments.
@@ -485,8 +568,11 @@ interface OpenAIClientOptions {
485
568
  interface OpenAIChatCompletionParams {
486
569
  model: string;
487
570
  messages: Array<{
488
- role: "system" | "user" | "assistant";
489
- content: string;
571
+ role: "system" | "user" | "assistant" | "tool";
572
+ content?: string | null;
573
+ name?: string;
574
+ tool_call_id?: string;
575
+ tool_calls?: ToolCall[];
490
576
  }>;
491
577
  max_tokens?: number;
492
578
  temperature?: number;
@@ -497,14 +583,17 @@ interface OpenAIChatCompletionParams {
497
583
  presence_penalty?: number;
498
584
  frequency_penalty?: number;
499
585
  user?: string;
586
+ tools?: Tool[];
587
+ tool_choice?: ToolChoice;
500
588
  }
501
589
  interface OpenAIChatCompletionChoice {
502
590
  index: number;
503
591
  message: {
504
592
  role: "assistant";
505
- content: string;
593
+ content?: string | null;
594
+ tool_calls?: ToolCall[];
506
595
  };
507
- finish_reason: string | null;
596
+ finish_reason: "stop" | "length" | "content_filter" | "tool_calls" | null;
508
597
  }
509
598
  interface OpenAIChatCompletionResponse {
510
599
  id: string;
@@ -584,4 +673,4 @@ declare class OpenAI {
584
673
  getWalletAddress(): string;
585
674
  }
586
675
 
587
- export { APIError, BASE_CHAIN_ID, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, ImageClient, type ImageClientOptions, type ImageData, type ImageGenerateOptions, type ImageModel, type ImageResponse, LLMClient, type LLMClientOptions, type Model, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PaymentError, type PaymentLinks, type RssSearchSource, type SearchParameters, type SearchSource, type Spending, USDC_BASE, USDC_BASE_CONTRACT, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getEip681Uri, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadWallet, saveWallet };
676
+ export { APIError, BASE_CHAIN_ID, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageGenerateOptions, type ImageModel, type ImageResponse, LLMClient, type LLMClientOptions, type Model, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PaymentError, type PaymentLinks, type RssSearchSource, type SearchParameters, type SearchSource, type Spending, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getEip681Uri, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadWallet, saveWallet, testnetClient };
package/dist/index.d.ts CHANGED
@@ -1,14 +1,42 @@
1
1
  /**
2
2
  * Type definitions for BlockRun LLM SDK
3
3
  */
4
+ interface FunctionDefinition {
5
+ name: string;
6
+ description?: string;
7
+ parameters?: Record<string, unknown>;
8
+ strict?: boolean;
9
+ }
10
+ interface Tool {
11
+ type: "function";
12
+ function: FunctionDefinition;
13
+ }
14
+ interface FunctionCall {
15
+ name: string;
16
+ arguments: string;
17
+ }
18
+ interface ToolCall {
19
+ id: string;
20
+ type: "function";
21
+ function: FunctionCall;
22
+ }
23
+ type ToolChoice = "none" | "auto" | "required" | {
24
+ type: "function";
25
+ function: {
26
+ name: string;
27
+ };
28
+ };
4
29
  interface ChatMessage {
5
- role: "system" | "user" | "assistant";
6
- content: string;
30
+ role: "system" | "user" | "assistant" | "tool";
31
+ content?: string | null;
32
+ name?: string;
33
+ tool_call_id?: string;
34
+ tool_calls?: ToolCall[];
7
35
  }
8
36
  interface ChatChoice {
9
37
  index: number;
10
38
  message: ChatMessage;
11
- finish_reason?: string;
39
+ finish_reason?: "stop" | "length" | "content_filter" | "tool_calls";
12
40
  }
13
41
  interface ChatUsage {
14
42
  prompt_tokens: number;
@@ -146,6 +174,10 @@ interface ChatCompletionOptions {
146
174
  search?: boolean;
147
175
  /** Full xAI Live Search configuration (for Grok models) */
148
176
  searchParameters?: SearchParameters;
177
+ /** Tool definitions for function calling */
178
+ tools?: Tool[];
179
+ /** Tool selection strategy */
180
+ toolChoice?: ToolChoice;
149
181
  }
150
182
  declare class BlockrunError extends Error {
151
183
  constructor(message: string);
@@ -180,8 +212,28 @@ declare class APIError extends BlockrunError {
180
212
  *
181
213
  * Provides access to multiple LLM providers (OpenAI, Anthropic, Google, etc.)
182
214
  * with automatic x402 micropayments on Base chain.
215
+ *
216
+ * Networks:
217
+ * - Mainnet: https://blockrun.ai/api (Base, Chain ID 8453)
218
+ * - Testnet: https://testnet.blockrun.ai/api (Base Sepolia, Chain ID 84532)
219
+ *
220
+ * @example Testnet usage
221
+ * ```ts
222
+ * // Use testnet convenience function
223
+ * import { testnetClient } from '@blockrun/llm';
224
+ * const client = testnetClient({ privateKey: '0x...' });
225
+ * const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
226
+ *
227
+ * // Or configure manually
228
+ * const client = new LLMClient({
229
+ * privateKey: '0x...',
230
+ * apiUrl: 'https://testnet.blockrun.ai/api'
231
+ * });
232
+ * ```
183
233
  */
184
234
  declare class LLMClient {
235
+ static readonly DEFAULT_API_URL = "https://blockrun.ai/api";
236
+ static readonly TESTNET_API_URL = "https://testnet.blockrun.ai/api";
185
237
  private account;
186
238
  private privateKey;
187
239
  private apiUrl;
@@ -266,7 +318,38 @@ declare class LLMClient {
266
318
  * Get the wallet address being used for payments.
267
319
  */
268
320
  getWalletAddress(): string;
321
+ /**
322
+ * Check if client is configured for testnet.
323
+ */
324
+ isTestnet(): boolean;
269
325
  }
326
+ /**
327
+ * Create a testnet LLM client for development and testing.
328
+ *
329
+ * This is a convenience function that creates an LLMClient configured
330
+ * for the BlockRun testnet (Base Sepolia).
331
+ *
332
+ * @param options - Client options (privateKey required unless BASE_CHAIN_WALLET_KEY env var is set)
333
+ * @returns LLMClient configured for testnet
334
+ *
335
+ * @example
336
+ * ```ts
337
+ * import { testnetClient } from '@blockrun/llm';
338
+ *
339
+ * const client = testnetClient({ privateKey: '0x...' });
340
+ * const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
341
+ * ```
342
+ *
343
+ * Testnet Setup:
344
+ * 1. Get testnet ETH from https://www.alchemy.com/faucets/base-sepolia
345
+ * 2. Get testnet USDC from https://faucet.circle.com/
346
+ * 3. Use your wallet with testnet funds
347
+ *
348
+ * Available Testnet Models:
349
+ * - openai/gpt-oss-20b
350
+ * - openai/gpt-oss-120b
351
+ */
352
+ declare function testnetClient(options?: Omit<LLMClientOptions, 'apiUrl'>): LLMClient;
270
353
 
271
354
  /**
272
355
  * BlockRun Image Client - Generate images via x402 micropayments.
@@ -485,8 +568,11 @@ interface OpenAIClientOptions {
485
568
  interface OpenAIChatCompletionParams {
486
569
  model: string;
487
570
  messages: Array<{
488
- role: "system" | "user" | "assistant";
489
- content: string;
571
+ role: "system" | "user" | "assistant" | "tool";
572
+ content?: string | null;
573
+ name?: string;
574
+ tool_call_id?: string;
575
+ tool_calls?: ToolCall[];
490
576
  }>;
491
577
  max_tokens?: number;
492
578
  temperature?: number;
@@ -497,14 +583,17 @@ interface OpenAIChatCompletionParams {
497
583
  presence_penalty?: number;
498
584
  frequency_penalty?: number;
499
585
  user?: string;
586
+ tools?: Tool[];
587
+ tool_choice?: ToolChoice;
500
588
  }
501
589
  interface OpenAIChatCompletionChoice {
502
590
  index: number;
503
591
  message: {
504
592
  role: "assistant";
505
- content: string;
593
+ content?: string | null;
594
+ tool_calls?: ToolCall[];
506
595
  };
507
- finish_reason: string | null;
596
+ finish_reason: "stop" | "length" | "content_filter" | "tool_calls" | null;
508
597
  }
509
598
  interface OpenAIChatCompletionResponse {
510
599
  id: string;
@@ -584,4 +673,4 @@ declare class OpenAI {
584
673
  getWalletAddress(): string;
585
674
  }
586
675
 
587
- export { APIError, BASE_CHAIN_ID, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, ImageClient, type ImageClientOptions, type ImageData, type ImageGenerateOptions, type ImageModel, type ImageResponse, LLMClient, type LLMClientOptions, type Model, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PaymentError, type PaymentLinks, type RssSearchSource, type SearchParameters, type SearchSource, type Spending, USDC_BASE, USDC_BASE_CONTRACT, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getEip681Uri, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadWallet, saveWallet };
676
+ export { APIError, BASE_CHAIN_ID, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageGenerateOptions, type ImageModel, type ImageResponse, LLMClient, type LLMClientOptions, type Model, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PaymentError, type PaymentLinks, type RssSearchSource, type SearchParameters, type SearchSource, type Spending, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getEip681Uri, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadWallet, saveWallet, testnetClient };
@@ -75,7 +75,7 @@ import {
75
75
  clusterApiUrl,
76
76
  sendAndConfirmRawTransaction,
77
77
  sendAndConfirmTransaction
78
- } from "./chunk-4LEERQOK.js";
78
+ } from "./chunk-S7BEMV6T.js";
79
79
  import "./chunk-2ESYSVXG.js";
80
80
  export {
81
81
  Account,
package/dist/index.js CHANGED
@@ -223,9 +223,14 @@ function validateResourceUrl(url, baseUrl) {
223
223
 
224
224
  // src/client.ts
225
225
  var DEFAULT_API_URL = "https://blockrun.ai/api";
226
+ var TESTNET_API_URL = "https://testnet.blockrun.ai/api";
226
227
  var DEFAULT_MAX_TOKENS = 1024;
227
228
  var DEFAULT_TIMEOUT = 6e4;
229
+ var SDK_VERSION = "0.3.0";
230
+ var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
228
231
  var LLMClient = class {
232
+ static DEFAULT_API_URL = DEFAULT_API_URL;
233
+ static TESTNET_API_URL = TESTNET_API_URL;
229
234
  account;
230
235
  privateKey;
231
236
  apiUrl;
@@ -278,7 +283,7 @@ var LLMClient = class {
278
283
  search: options?.search,
279
284
  searchParameters: options?.searchParameters
280
285
  });
281
- return result.choices[0].message.content;
286
+ return result.choices[0].message.content || "";
282
287
  }
283
288
  /**
284
289
  * Full chat completion interface (OpenAI-compatible).
@@ -305,6 +310,12 @@ var LLMClient = class {
305
310
  } else if (options?.search === true) {
306
311
  body.search_parameters = { mode: "on" };
307
312
  }
313
+ if (options?.tools !== void 0) {
314
+ body.tools = options.tools;
315
+ }
316
+ if (options?.toolChoice !== void 0) {
317
+ body.tool_choice = options.toolChoice;
318
+ }
308
319
  return this.requestWithPayment("/v1/chat/completions", body);
309
320
  }
310
321
  /**
@@ -314,7 +325,7 @@ var LLMClient = class {
314
325
  const url = `${this.apiUrl}${endpoint}`;
315
326
  const response = await this.fetchWithTimeout(url, {
316
327
  method: "POST",
317
- headers: { "Content-Type": "application/json" },
328
+ headers: { "Content-Type": "application/json", "User-Agent": USER_AGENT },
318
329
  body: JSON.stringify(body)
319
330
  });
320
331
  if (response.status === 402) {
@@ -377,6 +388,7 @@ var LLMClient = class {
377
388
  method: "POST",
378
389
  headers: {
379
390
  "Content-Type": "application/json",
391
+ "User-Agent": USER_AGENT,
380
392
  "PAYMENT-SIGNATURE": paymentPayload
381
393
  },
382
394
  body: JSON.stringify(body)
@@ -505,7 +517,19 @@ var LLMClient = class {
505
517
  getWalletAddress() {
506
518
  return this.account.address;
507
519
  }
520
+ /**
521
+ * Check if client is configured for testnet.
522
+ */
523
+ isTestnet() {
524
+ return this.apiUrl.includes("testnet.blockrun.ai");
525
+ }
508
526
  };
527
+ function testnetClient(options = {}) {
528
+ return new LLMClient({
529
+ ...options,
530
+ apiUrl: TESTNET_API_URL
531
+ });
532
+ }
509
533
  var client_default = LLMClient;
510
534
 
511
535
  // src/image.ts
@@ -907,7 +931,9 @@ var ChatCompletions = class {
907
931
  {
908
932
  maxTokens: params.max_tokens,
909
933
  temperature: params.temperature,
910
- topP: params.top_p
934
+ topP: params.top_p,
935
+ tools: params.tools,
936
+ toolChoice: params.tool_choice
911
937
  }
912
938
  );
913
939
  return this.transformResponse(response);
@@ -922,6 +948,12 @@ var ChatCompletions = class {
922
948
  top_p: params.top_p,
923
949
  stream: true
924
950
  };
951
+ if (params.tools) {
952
+ body.tools = params.tools;
953
+ }
954
+ if (params.tool_choice) {
955
+ body.tool_choice = params.tool_choice;
956
+ }
925
957
  const controller = new AbortController();
926
958
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
927
959
  try {
@@ -958,7 +990,8 @@ var ChatCompletions = class {
958
990
  index: choice.index ?? index,
959
991
  message: {
960
992
  role: "assistant",
961
- content: choice.message.content
993
+ content: choice.message.content,
994
+ tool_calls: choice.message.tool_calls
962
995
  },
963
996
  finish_reason: choice.finish_reason || "stop"
964
997
  })),
@@ -1015,5 +1048,6 @@ export {
1015
1048
  getPaymentLinks,
1016
1049
  getWalletAddress,
1017
1050
  loadWallet,
1018
- saveWallet
1051
+ saveWallet,
1052
+ testnetClient
1019
1053
  };
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@blockrun/llm",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "BlockRun LLM Gateway SDK - Pay-per-request AI via x402 on Base",
6
- "main": "dist/index.js",
7
- "module": "dist/index.mjs",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
11
  "types": "./dist/index.d.ts",
12
- "import": "./dist/index.mjs",
13
- "require": "./dist/index.js"
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
14
  }
15
15
  },
16
16
  "files": [