@blockrun/llm 0.2.1 → 1.0.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/README.md +156 -8
- package/dist/index.cjs +131 -6
- package/dist/index.d.cts +165 -8
- package/dist/index.d.ts +165 -8
- package/dist/index.js +129 -5
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Pay-per-request access to GPT-4o, Claude 4, Gemini 2.5, and more via x402 micropayments on Base and Solana.
|
|
4
4
|
|
|
5
|
-
**Networks:**
|
|
5
|
+
**Networks:**
|
|
6
|
+
- **Base Mainnet:** Chain ID 8453 - Production with real USDC
|
|
7
|
+
- **Base Sepolia (Testnet):** Chain ID 84532 - Developer testing with testnet USDC
|
|
8
|
+
- **Solana Mainnet** - Production with real USDC
|
|
9
|
+
|
|
6
10
|
**Payment:** USDC
|
|
7
11
|
**Protocol:** x402 v2 (CDP Facilitator)
|
|
8
12
|
|
|
@@ -55,12 +59,10 @@ For Solana, set `BLOCKRUN_SOLANA_KEY` environment variable with your base58-enco
|
|
|
55
59
|
| Model | Input Price | Output Price |
|
|
56
60
|
|-------|-------------|--------------|
|
|
57
61
|
| `openai/gpt-5.2` | $1.75/M | $14.00/M |
|
|
58
|
-
| `openai/gpt-5.1` | $1.25/M | $10.00/M |
|
|
59
|
-
| `openai/gpt-5` | $1.25/M | $10.00/M |
|
|
60
62
|
| `openai/gpt-5-mini` | $0.25/M | $2.00/M |
|
|
61
63
|
| `openai/gpt-5-nano` | $0.05/M | $0.40/M |
|
|
62
64
|
| `openai/gpt-5.2-pro` | $21.00/M | $168.00/M |
|
|
63
|
-
| `openai/gpt-5-
|
|
65
|
+
| `openai/gpt-5.2-codex` | $1.75/M | $14.00/M |
|
|
64
66
|
|
|
65
67
|
### OpenAI GPT-4 Family
|
|
66
68
|
| Model | Input Price | Output Price |
|
|
@@ -83,7 +85,10 @@ For Solana, set `BLOCKRUN_SOLANA_KEY` environment variable with your base58-enco
|
|
|
83
85
|
### Anthropic Claude
|
|
84
86
|
| Model | Input Price | Output Price |
|
|
85
87
|
|-------|-------------|--------------|
|
|
88
|
+
| `anthropic/claude-opus-4.6` | $5.00/M | $25.00/M |
|
|
89
|
+
| `anthropic/claude-opus-4.5` | $5.00/M | $25.00/M |
|
|
86
90
|
| `anthropic/claude-opus-4` | $15.00/M | $75.00/M |
|
|
91
|
+
| `anthropic/claude-sonnet-4.6` | $3.00/M | $15.00/M |
|
|
87
92
|
| `anthropic/claude-sonnet-4` | $3.00/M | $15.00/M |
|
|
88
93
|
| `anthropic/claude-haiku-4.5` | $1.00/M | $5.00/M |
|
|
89
94
|
|
|
@@ -92,7 +97,52 @@ For Solana, set `BLOCKRUN_SOLANA_KEY` environment variable with your base58-enco
|
|
|
92
97
|
|-------|-------------|--------------|
|
|
93
98
|
| `google/gemini-3-pro-preview` | $2.00/M | $12.00/M |
|
|
94
99
|
| `google/gemini-2.5-pro` | $1.25/M | $10.00/M |
|
|
95
|
-
| `google/gemini-2.5-flash` | $0.
|
|
100
|
+
| `google/gemini-2.5-flash` | $0.30/M | $2.50/M |
|
|
101
|
+
|
|
102
|
+
### DeepSeek
|
|
103
|
+
| Model | Input Price | Output Price |
|
|
104
|
+
|-------|-------------|--------------|
|
|
105
|
+
| `deepseek/deepseek-chat` | $0.28/M | $0.42/M |
|
|
106
|
+
| `deepseek/deepseek-reasoner` | $0.28/M | $0.42/M |
|
|
107
|
+
|
|
108
|
+
### xAI Grok
|
|
109
|
+
| Model | Input Price | Output Price | Context | Notes |
|
|
110
|
+
|-------|-------------|--------------|---------|-------|
|
|
111
|
+
| `xai/grok-3` | $3.00/M | $15.00/M | 131K | Flagship |
|
|
112
|
+
| `xai/grok-3-mini` | $0.30/M | $0.50/M | 131K | Fast & affordable |
|
|
113
|
+
| `xai/grok-4-1-fast-reasoning` | $0.20/M | $0.50/M | **2M** | Latest, chain-of-thought |
|
|
114
|
+
| `xai/grok-4-1-fast-non-reasoning` | $0.20/M | $0.50/M | **2M** | Latest, direct response |
|
|
115
|
+
| `xai/grok-4-fast-reasoning` | $0.20/M | $0.50/M | **2M** | Step-by-step reasoning |
|
|
116
|
+
| `xai/grok-4-fast-non-reasoning` | $0.20/M | $0.50/M | **2M** | Quick responses |
|
|
117
|
+
| `xai/grok-code-fast-1` | $0.20/M | $1.50/M | 256K | Code generation |
|
|
118
|
+
| `xai/grok-4-0709` | $0.20/M | $1.50/M | 256K | Premium quality |
|
|
119
|
+
| `xai/grok-2-vision` | $2.00/M | $10.00/M | 32K | Vision capabilities |
|
|
120
|
+
|
|
121
|
+
### Moonshot Kimi
|
|
122
|
+
| Model | Input Price | Output Price |
|
|
123
|
+
|-------|-------------|--------------|
|
|
124
|
+
| `moonshot/kimi-k2.5` | $0.60/M | $3.00/M |
|
|
125
|
+
|
|
126
|
+
### NVIDIA (Free & Hosted)
|
|
127
|
+
| Model | Input Price | Output Price | Notes |
|
|
128
|
+
|-------|-------------|--------------|-------|
|
|
129
|
+
| `nvidia/gpt-oss-120b` | **FREE** | **FREE** | OpenAI open-weight 120B (Apache 2.0) |
|
|
130
|
+
| `nvidia/kimi-k2.5` | $0.60/M | $3.00/M | Moonshot 1T MoE with vision |
|
|
131
|
+
|
|
132
|
+
### E2E Verified Models
|
|
133
|
+
|
|
134
|
+
All models below have been tested end-to-end via the TypeScript SDK (Feb 2026):
|
|
135
|
+
|
|
136
|
+
| Provider | Model | Status |
|
|
137
|
+
|----------|-------|--------|
|
|
138
|
+
| OpenAI | `openai/gpt-4o-mini` | Passed |
|
|
139
|
+
| OpenAI | `openai/gpt-5.2-codex` | Passed |
|
|
140
|
+
| Anthropic | `anthropic/claude-opus-4.6` | Passed |
|
|
141
|
+
| Anthropic | `anthropic/claude-sonnet-4` | Passed |
|
|
142
|
+
| Google | `google/gemini-2.5-flash` | Passed |
|
|
143
|
+
| DeepSeek | `deepseek/deepseek-chat` | Passed |
|
|
144
|
+
| xAI | `xai/grok-3` | Passed |
|
|
145
|
+
| Moonshot | `moonshot/kimi-k2.5` | Passed |
|
|
96
146
|
|
|
97
147
|
### Image Generation
|
|
98
148
|
| Model | Price |
|
|
@@ -103,6 +153,56 @@ For Solana, set `BLOCKRUN_SOLANA_KEY` environment variable with your base58-enco
|
|
|
103
153
|
| `google/nano-banana-pro` | $0.10-0.15/image |
|
|
104
154
|
| `black-forest/flux-1.1-pro` | $0.04/image |
|
|
105
155
|
|
|
156
|
+
### Testnet Models (Base Sepolia)
|
|
157
|
+
| Model | Price |
|
|
158
|
+
|-------|-------|
|
|
159
|
+
| `openai/gpt-oss-20b` | $0.001/request |
|
|
160
|
+
| `openai/gpt-oss-120b` | $0.002/request |
|
|
161
|
+
|
|
162
|
+
*Testnet models use flat pricing (no token counting) for simplicity.*
|
|
163
|
+
|
|
164
|
+
## Testnet Usage
|
|
165
|
+
|
|
166
|
+
For development and testing without real USDC, use the testnet:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { testnetClient } from '@blockrun/llm';
|
|
170
|
+
|
|
171
|
+
// Create testnet client (uses Base Sepolia)
|
|
172
|
+
const client = testnetClient({ privateKey: '0x...' });
|
|
173
|
+
|
|
174
|
+
// Chat with testnet model
|
|
175
|
+
const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
|
|
176
|
+
console.log(response);
|
|
177
|
+
|
|
178
|
+
// Check if client is on testnet
|
|
179
|
+
console.log(client.isTestnet()); // true
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Testnet Setup
|
|
183
|
+
|
|
184
|
+
1. Get testnet ETH from [Alchemy Base Sepolia Faucet](https://www.alchemy.com/faucets/base-sepolia)
|
|
185
|
+
2. Get testnet USDC from [Circle USDC Faucet](https://faucet.circle.com/)
|
|
186
|
+
3. Set your wallet key: `export BASE_CHAIN_WALLET_KEY=0x...`
|
|
187
|
+
|
|
188
|
+
### Available Testnet Models
|
|
189
|
+
|
|
190
|
+
- `openai/gpt-oss-20b` - $0.001/request (flat price)
|
|
191
|
+
- `openai/gpt-oss-120b` - $0.002/request (flat price)
|
|
192
|
+
|
|
193
|
+
### Manual Testnet Configuration
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { LLMClient } from '@blockrun/llm';
|
|
197
|
+
|
|
198
|
+
// Or configure manually
|
|
199
|
+
const client = new LLMClient({
|
|
200
|
+
privateKey: '0x...',
|
|
201
|
+
apiUrl: 'https://testnet.blockrun.ai/api'
|
|
202
|
+
});
|
|
203
|
+
const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
|
|
204
|
+
```
|
|
205
|
+
|
|
106
206
|
## Usage Examples
|
|
107
207
|
|
|
108
208
|
### Simple Chat
|
|
@@ -121,6 +221,47 @@ const response2 = await client.chat('anthropic/claude-sonnet-4', 'Write a haiku'
|
|
|
121
221
|
});
|
|
122
222
|
```
|
|
123
223
|
|
|
224
|
+
### Smart Routing (ClawRouter)
|
|
225
|
+
|
|
226
|
+
Save up to 78% on inference costs with intelligent model routing. ClawRouter uses a 14-dimension rule-based scoring algorithm to select the cheapest model that can handle your request (<1ms, 100% local).
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { LLMClient } from '@blockrun/llm';
|
|
230
|
+
|
|
231
|
+
const client = new LLMClient();
|
|
232
|
+
|
|
233
|
+
// Auto-route to cheapest capable model
|
|
234
|
+
const result = await client.smartChat('What is 2+2?');
|
|
235
|
+
console.log(result.response); // '4'
|
|
236
|
+
console.log(result.model); // 'google/gemini-2.5-flash'
|
|
237
|
+
console.log(result.routing.tier); // 'SIMPLE'
|
|
238
|
+
console.log(`Saved ${(result.routing.savings * 100).toFixed(0)}%`); // 'Saved 78%'
|
|
239
|
+
|
|
240
|
+
// Routing profiles
|
|
241
|
+
const free = await client.smartChat('Hello!', { routingProfile: 'free' }); // Zero cost
|
|
242
|
+
const eco = await client.smartChat('Explain AI', { routingProfile: 'eco' }); // Budget optimized
|
|
243
|
+
const auto = await client.smartChat('Code review', { routingProfile: 'auto' }); // Balanced (default)
|
|
244
|
+
const premium = await client.smartChat('Write a legal brief', { routingProfile: 'premium' }); // Best quality
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Routing Profiles:**
|
|
248
|
+
|
|
249
|
+
| Profile | Description | Best For |
|
|
250
|
+
|---------|-------------|----------|
|
|
251
|
+
| `free` | NVIDIA free models only | Testing, simple queries |
|
|
252
|
+
| `eco` | Budget-optimized | Cost-sensitive workloads |
|
|
253
|
+
| `auto` | Intelligent routing (default) | General use |
|
|
254
|
+
| `premium` | Best quality models | Critical tasks |
|
|
255
|
+
|
|
256
|
+
**Tiers:**
|
|
257
|
+
|
|
258
|
+
| Tier | Example Tasks | Typical Models |
|
|
259
|
+
|------|---------------|----------------|
|
|
260
|
+
| SIMPLE | Greetings, math, lookups | Gemini Flash, GPT-4o-mini |
|
|
261
|
+
| MEDIUM | Explanations, summaries | GPT-4o, Claude Sonnet |
|
|
262
|
+
| COMPLEX | Analysis, code generation | GPT-5.2, Claude Opus |
|
|
263
|
+
| REASONING | Multi-step logic, planning | o3, DeepSeek Reasoner |
|
|
264
|
+
|
|
124
265
|
### Full Chat Completion
|
|
125
266
|
|
|
126
267
|
```typescript
|
|
@@ -299,10 +440,17 @@ Full TypeScript support with exported types:
|
|
|
299
440
|
```typescript
|
|
300
441
|
import {
|
|
301
442
|
LLMClient,
|
|
443
|
+
testnetClient,
|
|
302
444
|
type ChatMessage,
|
|
303
445
|
type ChatResponse,
|
|
304
446
|
type ChatOptions,
|
|
305
447
|
type Model,
|
|
448
|
+
// Smart routing types
|
|
449
|
+
type SmartChatOptions,
|
|
450
|
+
type SmartChatResponse,
|
|
451
|
+
type RoutingDecision,
|
|
452
|
+
type RoutingProfile,
|
|
453
|
+
type RoutingTier,
|
|
306
454
|
APIError,
|
|
307
455
|
PaymentError,
|
|
308
456
|
} from '@blockrun/llm';
|
|
@@ -311,9 +459,9 @@ import {
|
|
|
311
459
|
## Links
|
|
312
460
|
|
|
313
461
|
- [Website](https://blockrun.ai)
|
|
314
|
-
- [Documentation](https://
|
|
315
|
-
- [GitHub](https://github.com/
|
|
316
|
-
- [
|
|
462
|
+
- [Documentation](https://github.com/BlockRunAI/awesome-blockrun/tree/main/docs)
|
|
463
|
+
- [GitHub](https://github.com/blockrunai/blockrun-llm-ts)
|
|
464
|
+
- [Telegram](https://t.me/+mroQv4-4hGgzOGUx)
|
|
317
465
|
|
|
318
466
|
## License
|
|
319
467
|
|
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
|
|
|
@@ -82,6 +83,9 @@ var APIError = class extends BlockrunError {
|
|
|
82
83
|
}
|
|
83
84
|
};
|
|
84
85
|
|
|
86
|
+
// src/client.ts
|
|
87
|
+
var import_clawrouter = require("@blockrun/clawrouter");
|
|
88
|
+
|
|
85
89
|
// src/x402.ts
|
|
86
90
|
var import_accounts = require("viem/accounts");
|
|
87
91
|
var BASE_CHAIN_ID = 8453;
|
|
@@ -278,15 +282,22 @@ function validateResourceUrl(url, baseUrl) {
|
|
|
278
282
|
|
|
279
283
|
// src/client.ts
|
|
280
284
|
var DEFAULT_API_URL = "https://blockrun.ai/api";
|
|
285
|
+
var TESTNET_API_URL = "https://testnet.blockrun.ai/api";
|
|
281
286
|
var DEFAULT_MAX_TOKENS = 1024;
|
|
282
287
|
var DEFAULT_TIMEOUT = 6e4;
|
|
288
|
+
var SDK_VERSION = "0.3.0";
|
|
289
|
+
var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
|
|
283
290
|
var LLMClient = class {
|
|
291
|
+
static DEFAULT_API_URL = DEFAULT_API_URL;
|
|
292
|
+
static TESTNET_API_URL = TESTNET_API_URL;
|
|
284
293
|
account;
|
|
285
294
|
privateKey;
|
|
286
295
|
apiUrl;
|
|
287
296
|
timeout;
|
|
288
297
|
sessionTotalUsd = 0;
|
|
289
298
|
sessionCalls = 0;
|
|
299
|
+
modelPricingCache = null;
|
|
300
|
+
modelPricingPromise = null;
|
|
290
301
|
/**
|
|
291
302
|
* Initialize the BlockRun LLM client.
|
|
292
303
|
*
|
|
@@ -333,7 +344,92 @@ var LLMClient = class {
|
|
|
333
344
|
search: options?.search,
|
|
334
345
|
searchParameters: options?.searchParameters
|
|
335
346
|
});
|
|
336
|
-
return result.choices[0].message.content;
|
|
347
|
+
return result.choices[0].message.content || "";
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Smart chat with automatic model routing.
|
|
351
|
+
*
|
|
352
|
+
* Uses ClawRouter's 14-dimension rule-based scoring algorithm (<1ms, 100% local)
|
|
353
|
+
* to select the cheapest model that can handle your request.
|
|
354
|
+
*
|
|
355
|
+
* @param prompt - User message
|
|
356
|
+
* @param options - Optional chat and routing parameters
|
|
357
|
+
* @returns SmartChatResponse with response text, selected model, and routing metadata
|
|
358
|
+
*
|
|
359
|
+
* @example Simple usage (auto profile)
|
|
360
|
+
* ```ts
|
|
361
|
+
* const result = await client.smartChat('What is 2+2?');
|
|
362
|
+
* console.log(result.response); // '4'
|
|
363
|
+
* console.log(result.model); // 'google/gemini-2.5-flash'
|
|
364
|
+
* console.log(result.routing.savings); // 0.78 (78% savings)
|
|
365
|
+
* ```
|
|
366
|
+
*
|
|
367
|
+
* @example With routing profile
|
|
368
|
+
* ```ts
|
|
369
|
+
* // Free tier only (zero cost)
|
|
370
|
+
* const result = await client.smartChat('Hello!', { routingProfile: 'free' });
|
|
371
|
+
*
|
|
372
|
+
* // Eco mode (budget optimized)
|
|
373
|
+
* const result = await client.smartChat('Explain quantum computing', { routingProfile: 'eco' });
|
|
374
|
+
*
|
|
375
|
+
* // Premium mode (best quality)
|
|
376
|
+
* const result = await client.smartChat('Write a business plan', { routingProfile: 'premium' });
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
async smartChat(prompt, options) {
|
|
380
|
+
const modelPricing = await this.getModelPricing();
|
|
381
|
+
const maxOutputTokens = options?.maxOutputTokens || options?.maxTokens || 1024;
|
|
382
|
+
const decision = (0, import_clawrouter.route)(prompt, options?.system, maxOutputTokens, {
|
|
383
|
+
config: import_clawrouter.DEFAULT_ROUTING_CONFIG,
|
|
384
|
+
modelPricing,
|
|
385
|
+
routingProfile: options?.routingProfile
|
|
386
|
+
});
|
|
387
|
+
const response = await this.chat(decision.model, prompt, {
|
|
388
|
+
system: options?.system,
|
|
389
|
+
maxTokens: options?.maxTokens,
|
|
390
|
+
temperature: options?.temperature,
|
|
391
|
+
topP: options?.topP,
|
|
392
|
+
search: options?.search,
|
|
393
|
+
searchParameters: options?.searchParameters
|
|
394
|
+
});
|
|
395
|
+
return {
|
|
396
|
+
response,
|
|
397
|
+
model: decision.model,
|
|
398
|
+
routing: decision
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Get model pricing map (cached).
|
|
403
|
+
* Fetches from API on first call, then returns cached result.
|
|
404
|
+
*/
|
|
405
|
+
async getModelPricing() {
|
|
406
|
+
if (this.modelPricingCache) {
|
|
407
|
+
return this.modelPricingCache;
|
|
408
|
+
}
|
|
409
|
+
if (this.modelPricingPromise) {
|
|
410
|
+
return this.modelPricingPromise;
|
|
411
|
+
}
|
|
412
|
+
this.modelPricingPromise = this.fetchModelPricing();
|
|
413
|
+
try {
|
|
414
|
+
this.modelPricingCache = await this.modelPricingPromise;
|
|
415
|
+
return this.modelPricingCache;
|
|
416
|
+
} finally {
|
|
417
|
+
this.modelPricingPromise = null;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Fetch model pricing from API.
|
|
422
|
+
*/
|
|
423
|
+
async fetchModelPricing() {
|
|
424
|
+
const models = await this.listModels();
|
|
425
|
+
const pricing = /* @__PURE__ */ new Map();
|
|
426
|
+
for (const model of models) {
|
|
427
|
+
pricing.set(model.id, {
|
|
428
|
+
inputPrice: model.inputPrice,
|
|
429
|
+
outputPrice: model.outputPrice
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
return pricing;
|
|
337
433
|
}
|
|
338
434
|
/**
|
|
339
435
|
* Full chat completion interface (OpenAI-compatible).
|
|
@@ -360,6 +456,12 @@ var LLMClient = class {
|
|
|
360
456
|
} else if (options?.search === true) {
|
|
361
457
|
body.search_parameters = { mode: "on" };
|
|
362
458
|
}
|
|
459
|
+
if (options?.tools !== void 0) {
|
|
460
|
+
body.tools = options.tools;
|
|
461
|
+
}
|
|
462
|
+
if (options?.toolChoice !== void 0) {
|
|
463
|
+
body.tool_choice = options.toolChoice;
|
|
464
|
+
}
|
|
363
465
|
return this.requestWithPayment("/v1/chat/completions", body);
|
|
364
466
|
}
|
|
365
467
|
/**
|
|
@@ -369,7 +471,7 @@ var LLMClient = class {
|
|
|
369
471
|
const url = `${this.apiUrl}${endpoint}`;
|
|
370
472
|
const response = await this.fetchWithTimeout(url, {
|
|
371
473
|
method: "POST",
|
|
372
|
-
headers: { "Content-Type": "application/json" },
|
|
474
|
+
headers: { "Content-Type": "application/json", "User-Agent": USER_AGENT },
|
|
373
475
|
body: JSON.stringify(body)
|
|
374
476
|
});
|
|
375
477
|
if (response.status === 402) {
|
|
@@ -432,6 +534,7 @@ var LLMClient = class {
|
|
|
432
534
|
method: "POST",
|
|
433
535
|
headers: {
|
|
434
536
|
"Content-Type": "application/json",
|
|
537
|
+
"User-Agent": USER_AGENT,
|
|
435
538
|
"PAYMENT-SIGNATURE": paymentPayload
|
|
436
539
|
},
|
|
437
540
|
body: JSON.stringify(body)
|
|
@@ -560,7 +663,19 @@ var LLMClient = class {
|
|
|
560
663
|
getWalletAddress() {
|
|
561
664
|
return this.account.address;
|
|
562
665
|
}
|
|
666
|
+
/**
|
|
667
|
+
* Check if client is configured for testnet.
|
|
668
|
+
*/
|
|
669
|
+
isTestnet() {
|
|
670
|
+
return this.apiUrl.includes("testnet.blockrun.ai");
|
|
671
|
+
}
|
|
563
672
|
};
|
|
673
|
+
function testnetClient(options = {}) {
|
|
674
|
+
return new LLMClient({
|
|
675
|
+
...options,
|
|
676
|
+
apiUrl: TESTNET_API_URL
|
|
677
|
+
});
|
|
678
|
+
}
|
|
564
679
|
var client_default = LLMClient;
|
|
565
680
|
|
|
566
681
|
// src/image.ts
|
|
@@ -962,7 +1077,9 @@ var ChatCompletions = class {
|
|
|
962
1077
|
{
|
|
963
1078
|
maxTokens: params.max_tokens,
|
|
964
1079
|
temperature: params.temperature,
|
|
965
|
-
topP: params.top_p
|
|
1080
|
+
topP: params.top_p,
|
|
1081
|
+
tools: params.tools,
|
|
1082
|
+
toolChoice: params.tool_choice
|
|
966
1083
|
}
|
|
967
1084
|
);
|
|
968
1085
|
return this.transformResponse(response);
|
|
@@ -977,6 +1094,12 @@ var ChatCompletions = class {
|
|
|
977
1094
|
top_p: params.top_p,
|
|
978
1095
|
stream: true
|
|
979
1096
|
};
|
|
1097
|
+
if (params.tools) {
|
|
1098
|
+
body.tools = params.tools;
|
|
1099
|
+
}
|
|
1100
|
+
if (params.tool_choice) {
|
|
1101
|
+
body.tool_choice = params.tool_choice;
|
|
1102
|
+
}
|
|
980
1103
|
const controller = new AbortController();
|
|
981
1104
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
982
1105
|
try {
|
|
@@ -1013,7 +1136,8 @@ var ChatCompletions = class {
|
|
|
1013
1136
|
index: choice.index ?? index,
|
|
1014
1137
|
message: {
|
|
1015
1138
|
role: "assistant",
|
|
1016
|
-
content: choice.message.content
|
|
1139
|
+
content: choice.message.content,
|
|
1140
|
+
tool_calls: choice.message.tool_calls
|
|
1017
1141
|
},
|
|
1018
1142
|
finish_reason: choice.finish_reason || "stop"
|
|
1019
1143
|
})),
|
|
@@ -1070,5 +1194,6 @@ var OpenAI = class {
|
|
|
1070
1194
|
getPaymentLinks,
|
|
1071
1195
|
getWalletAddress,
|
|
1072
1196
|
loadWallet,
|
|
1073
|
-
saveWallet
|
|
1197
|
+
saveWallet,
|
|
1198
|
+
testnetClient
|
|
1074
1199
|
});
|
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
|
|
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?:
|
|
39
|
+
finish_reason?: "stop" | "length" | "content_filter" | "tool_calls";
|
|
12
40
|
}
|
|
13
41
|
interface ChatUsage {
|
|
14
42
|
prompt_tokens: number;
|
|
@@ -146,6 +174,36 @@ 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;
|
|
181
|
+
}
|
|
182
|
+
type RoutingProfile = "free" | "eco" | "auto" | "premium";
|
|
183
|
+
type RoutingTier = "SIMPLE" | "MEDIUM" | "COMPLEX" | "REASONING";
|
|
184
|
+
interface RoutingDecision {
|
|
185
|
+
model: string;
|
|
186
|
+
tier: RoutingTier;
|
|
187
|
+
confidence: number;
|
|
188
|
+
method: "rules" | "llm";
|
|
189
|
+
reasoning: string;
|
|
190
|
+
costEstimate: number;
|
|
191
|
+
baselineCost: number;
|
|
192
|
+
savings: number;
|
|
193
|
+
}
|
|
194
|
+
interface SmartChatOptions extends ChatOptions {
|
|
195
|
+
/** Routing profile: free (zero cost), eco (budget), auto (balanced), premium (best quality) */
|
|
196
|
+
routingProfile?: RoutingProfile;
|
|
197
|
+
/** Maximum output tokens (used for cost estimation) */
|
|
198
|
+
maxOutputTokens?: number;
|
|
199
|
+
}
|
|
200
|
+
interface SmartChatResponse {
|
|
201
|
+
/** The AI response text */
|
|
202
|
+
response: string;
|
|
203
|
+
/** Which model was selected by smart routing */
|
|
204
|
+
model: string;
|
|
205
|
+
/** Routing decision metadata */
|
|
206
|
+
routing: RoutingDecision;
|
|
149
207
|
}
|
|
150
208
|
declare class BlockrunError extends Error {
|
|
151
209
|
constructor(message: string);
|
|
@@ -180,14 +238,36 @@ declare class APIError extends BlockrunError {
|
|
|
180
238
|
*
|
|
181
239
|
* Provides access to multiple LLM providers (OpenAI, Anthropic, Google, etc.)
|
|
182
240
|
* with automatic x402 micropayments on Base chain.
|
|
241
|
+
*
|
|
242
|
+
* Networks:
|
|
243
|
+
* - Mainnet: https://blockrun.ai/api (Base, Chain ID 8453)
|
|
244
|
+
* - Testnet: https://testnet.blockrun.ai/api (Base Sepolia, Chain ID 84532)
|
|
245
|
+
*
|
|
246
|
+
* @example Testnet usage
|
|
247
|
+
* ```ts
|
|
248
|
+
* // Use testnet convenience function
|
|
249
|
+
* import { testnetClient } from '@blockrun/llm';
|
|
250
|
+
* const client = testnetClient({ privateKey: '0x...' });
|
|
251
|
+
* const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
|
|
252
|
+
*
|
|
253
|
+
* // Or configure manually
|
|
254
|
+
* const client = new LLMClient({
|
|
255
|
+
* privateKey: '0x...',
|
|
256
|
+
* apiUrl: 'https://testnet.blockrun.ai/api'
|
|
257
|
+
* });
|
|
258
|
+
* ```
|
|
183
259
|
*/
|
|
184
260
|
declare class LLMClient {
|
|
261
|
+
static readonly DEFAULT_API_URL = "https://blockrun.ai/api";
|
|
262
|
+
static readonly TESTNET_API_URL = "https://testnet.blockrun.ai/api";
|
|
185
263
|
private account;
|
|
186
264
|
private privateKey;
|
|
187
265
|
private apiUrl;
|
|
188
266
|
private timeout;
|
|
189
267
|
private sessionTotalUsd;
|
|
190
268
|
private sessionCalls;
|
|
269
|
+
private modelPricingCache;
|
|
270
|
+
private modelPricingPromise;
|
|
191
271
|
/**
|
|
192
272
|
* Initialize the BlockRun LLM client.
|
|
193
273
|
*
|
|
@@ -207,6 +287,46 @@ declare class LLMClient {
|
|
|
207
287
|
* console.log(response); // 'The capital of France is Paris.'
|
|
208
288
|
*/
|
|
209
289
|
chat(model: string, prompt: string, options?: ChatOptions): Promise<string>;
|
|
290
|
+
/**
|
|
291
|
+
* Smart chat with automatic model routing.
|
|
292
|
+
*
|
|
293
|
+
* Uses ClawRouter's 14-dimension rule-based scoring algorithm (<1ms, 100% local)
|
|
294
|
+
* to select the cheapest model that can handle your request.
|
|
295
|
+
*
|
|
296
|
+
* @param prompt - User message
|
|
297
|
+
* @param options - Optional chat and routing parameters
|
|
298
|
+
* @returns SmartChatResponse with response text, selected model, and routing metadata
|
|
299
|
+
*
|
|
300
|
+
* @example Simple usage (auto profile)
|
|
301
|
+
* ```ts
|
|
302
|
+
* const result = await client.smartChat('What is 2+2?');
|
|
303
|
+
* console.log(result.response); // '4'
|
|
304
|
+
* console.log(result.model); // 'google/gemini-2.5-flash'
|
|
305
|
+
* console.log(result.routing.savings); // 0.78 (78% savings)
|
|
306
|
+
* ```
|
|
307
|
+
*
|
|
308
|
+
* @example With routing profile
|
|
309
|
+
* ```ts
|
|
310
|
+
* // Free tier only (zero cost)
|
|
311
|
+
* const result = await client.smartChat('Hello!', { routingProfile: 'free' });
|
|
312
|
+
*
|
|
313
|
+
* // Eco mode (budget optimized)
|
|
314
|
+
* const result = await client.smartChat('Explain quantum computing', { routingProfile: 'eco' });
|
|
315
|
+
*
|
|
316
|
+
* // Premium mode (best quality)
|
|
317
|
+
* const result = await client.smartChat('Write a business plan', { routingProfile: 'premium' });
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
smartChat(prompt: string, options?: SmartChatOptions): Promise<SmartChatResponse>;
|
|
321
|
+
/**
|
|
322
|
+
* Get model pricing map (cached).
|
|
323
|
+
* Fetches from API on first call, then returns cached result.
|
|
324
|
+
*/
|
|
325
|
+
private getModelPricing;
|
|
326
|
+
/**
|
|
327
|
+
* Fetch model pricing from API.
|
|
328
|
+
*/
|
|
329
|
+
private fetchModelPricing;
|
|
210
330
|
/**
|
|
211
331
|
* Full chat completion interface (OpenAI-compatible).
|
|
212
332
|
*
|
|
@@ -266,7 +386,38 @@ declare class LLMClient {
|
|
|
266
386
|
* Get the wallet address being used for payments.
|
|
267
387
|
*/
|
|
268
388
|
getWalletAddress(): string;
|
|
389
|
+
/**
|
|
390
|
+
* Check if client is configured for testnet.
|
|
391
|
+
*/
|
|
392
|
+
isTestnet(): boolean;
|
|
269
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* Create a testnet LLM client for development and testing.
|
|
396
|
+
*
|
|
397
|
+
* This is a convenience function that creates an LLMClient configured
|
|
398
|
+
* for the BlockRun testnet (Base Sepolia).
|
|
399
|
+
*
|
|
400
|
+
* @param options - Client options (privateKey required unless BASE_CHAIN_WALLET_KEY env var is set)
|
|
401
|
+
* @returns LLMClient configured for testnet
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* ```ts
|
|
405
|
+
* import { testnetClient } from '@blockrun/llm';
|
|
406
|
+
*
|
|
407
|
+
* const client = testnetClient({ privateKey: '0x...' });
|
|
408
|
+
* const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
|
|
409
|
+
* ```
|
|
410
|
+
*
|
|
411
|
+
* Testnet Setup:
|
|
412
|
+
* 1. Get testnet ETH from https://www.alchemy.com/faucets/base-sepolia
|
|
413
|
+
* 2. Get testnet USDC from https://faucet.circle.com/
|
|
414
|
+
* 3. Use your wallet with testnet funds
|
|
415
|
+
*
|
|
416
|
+
* Available Testnet Models:
|
|
417
|
+
* - openai/gpt-oss-20b
|
|
418
|
+
* - openai/gpt-oss-120b
|
|
419
|
+
*/
|
|
420
|
+
declare function testnetClient(options?: Omit<LLMClientOptions, 'apiUrl'>): LLMClient;
|
|
270
421
|
|
|
271
422
|
/**
|
|
272
423
|
* BlockRun Image Client - Generate images via x402 micropayments.
|
|
@@ -485,8 +636,11 @@ interface OpenAIClientOptions {
|
|
|
485
636
|
interface OpenAIChatCompletionParams {
|
|
486
637
|
model: string;
|
|
487
638
|
messages: Array<{
|
|
488
|
-
role: "system" | "user" | "assistant";
|
|
489
|
-
content
|
|
639
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
640
|
+
content?: string | null;
|
|
641
|
+
name?: string;
|
|
642
|
+
tool_call_id?: string;
|
|
643
|
+
tool_calls?: ToolCall[];
|
|
490
644
|
}>;
|
|
491
645
|
max_tokens?: number;
|
|
492
646
|
temperature?: number;
|
|
@@ -497,14 +651,17 @@ interface OpenAIChatCompletionParams {
|
|
|
497
651
|
presence_penalty?: number;
|
|
498
652
|
frequency_penalty?: number;
|
|
499
653
|
user?: string;
|
|
654
|
+
tools?: Tool[];
|
|
655
|
+
tool_choice?: ToolChoice;
|
|
500
656
|
}
|
|
501
657
|
interface OpenAIChatCompletionChoice {
|
|
502
658
|
index: number;
|
|
503
659
|
message: {
|
|
504
660
|
role: "assistant";
|
|
505
|
-
content
|
|
661
|
+
content?: string | null;
|
|
662
|
+
tool_calls?: ToolCall[];
|
|
506
663
|
};
|
|
507
|
-
finish_reason:
|
|
664
|
+
finish_reason: "stop" | "length" | "content_filter" | "tool_calls" | null;
|
|
508
665
|
}
|
|
509
666
|
interface OpenAIChatCompletionResponse {
|
|
510
667
|
id: string;
|
|
@@ -584,4 +741,4 @@ declare class OpenAI {
|
|
|
584
741
|
getWalletAddress(): string;
|
|
585
742
|
}
|
|
586
743
|
|
|
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 };
|
|
744
|
+
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 RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, type SearchParameters, type SearchSource, type SmartChatOptions, type SmartChatResponse, 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
|
|
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?:
|
|
39
|
+
finish_reason?: "stop" | "length" | "content_filter" | "tool_calls";
|
|
12
40
|
}
|
|
13
41
|
interface ChatUsage {
|
|
14
42
|
prompt_tokens: number;
|
|
@@ -146,6 +174,36 @@ 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;
|
|
181
|
+
}
|
|
182
|
+
type RoutingProfile = "free" | "eco" | "auto" | "premium";
|
|
183
|
+
type RoutingTier = "SIMPLE" | "MEDIUM" | "COMPLEX" | "REASONING";
|
|
184
|
+
interface RoutingDecision {
|
|
185
|
+
model: string;
|
|
186
|
+
tier: RoutingTier;
|
|
187
|
+
confidence: number;
|
|
188
|
+
method: "rules" | "llm";
|
|
189
|
+
reasoning: string;
|
|
190
|
+
costEstimate: number;
|
|
191
|
+
baselineCost: number;
|
|
192
|
+
savings: number;
|
|
193
|
+
}
|
|
194
|
+
interface SmartChatOptions extends ChatOptions {
|
|
195
|
+
/** Routing profile: free (zero cost), eco (budget), auto (balanced), premium (best quality) */
|
|
196
|
+
routingProfile?: RoutingProfile;
|
|
197
|
+
/** Maximum output tokens (used for cost estimation) */
|
|
198
|
+
maxOutputTokens?: number;
|
|
199
|
+
}
|
|
200
|
+
interface SmartChatResponse {
|
|
201
|
+
/** The AI response text */
|
|
202
|
+
response: string;
|
|
203
|
+
/** Which model was selected by smart routing */
|
|
204
|
+
model: string;
|
|
205
|
+
/** Routing decision metadata */
|
|
206
|
+
routing: RoutingDecision;
|
|
149
207
|
}
|
|
150
208
|
declare class BlockrunError extends Error {
|
|
151
209
|
constructor(message: string);
|
|
@@ -180,14 +238,36 @@ declare class APIError extends BlockrunError {
|
|
|
180
238
|
*
|
|
181
239
|
* Provides access to multiple LLM providers (OpenAI, Anthropic, Google, etc.)
|
|
182
240
|
* with automatic x402 micropayments on Base chain.
|
|
241
|
+
*
|
|
242
|
+
* Networks:
|
|
243
|
+
* - Mainnet: https://blockrun.ai/api (Base, Chain ID 8453)
|
|
244
|
+
* - Testnet: https://testnet.blockrun.ai/api (Base Sepolia, Chain ID 84532)
|
|
245
|
+
*
|
|
246
|
+
* @example Testnet usage
|
|
247
|
+
* ```ts
|
|
248
|
+
* // Use testnet convenience function
|
|
249
|
+
* import { testnetClient } from '@blockrun/llm';
|
|
250
|
+
* const client = testnetClient({ privateKey: '0x...' });
|
|
251
|
+
* const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
|
|
252
|
+
*
|
|
253
|
+
* // Or configure manually
|
|
254
|
+
* const client = new LLMClient({
|
|
255
|
+
* privateKey: '0x...',
|
|
256
|
+
* apiUrl: 'https://testnet.blockrun.ai/api'
|
|
257
|
+
* });
|
|
258
|
+
* ```
|
|
183
259
|
*/
|
|
184
260
|
declare class LLMClient {
|
|
261
|
+
static readonly DEFAULT_API_URL = "https://blockrun.ai/api";
|
|
262
|
+
static readonly TESTNET_API_URL = "https://testnet.blockrun.ai/api";
|
|
185
263
|
private account;
|
|
186
264
|
private privateKey;
|
|
187
265
|
private apiUrl;
|
|
188
266
|
private timeout;
|
|
189
267
|
private sessionTotalUsd;
|
|
190
268
|
private sessionCalls;
|
|
269
|
+
private modelPricingCache;
|
|
270
|
+
private modelPricingPromise;
|
|
191
271
|
/**
|
|
192
272
|
* Initialize the BlockRun LLM client.
|
|
193
273
|
*
|
|
@@ -207,6 +287,46 @@ declare class LLMClient {
|
|
|
207
287
|
* console.log(response); // 'The capital of France is Paris.'
|
|
208
288
|
*/
|
|
209
289
|
chat(model: string, prompt: string, options?: ChatOptions): Promise<string>;
|
|
290
|
+
/**
|
|
291
|
+
* Smart chat with automatic model routing.
|
|
292
|
+
*
|
|
293
|
+
* Uses ClawRouter's 14-dimension rule-based scoring algorithm (<1ms, 100% local)
|
|
294
|
+
* to select the cheapest model that can handle your request.
|
|
295
|
+
*
|
|
296
|
+
* @param prompt - User message
|
|
297
|
+
* @param options - Optional chat and routing parameters
|
|
298
|
+
* @returns SmartChatResponse with response text, selected model, and routing metadata
|
|
299
|
+
*
|
|
300
|
+
* @example Simple usage (auto profile)
|
|
301
|
+
* ```ts
|
|
302
|
+
* const result = await client.smartChat('What is 2+2?');
|
|
303
|
+
* console.log(result.response); // '4'
|
|
304
|
+
* console.log(result.model); // 'google/gemini-2.5-flash'
|
|
305
|
+
* console.log(result.routing.savings); // 0.78 (78% savings)
|
|
306
|
+
* ```
|
|
307
|
+
*
|
|
308
|
+
* @example With routing profile
|
|
309
|
+
* ```ts
|
|
310
|
+
* // Free tier only (zero cost)
|
|
311
|
+
* const result = await client.smartChat('Hello!', { routingProfile: 'free' });
|
|
312
|
+
*
|
|
313
|
+
* // Eco mode (budget optimized)
|
|
314
|
+
* const result = await client.smartChat('Explain quantum computing', { routingProfile: 'eco' });
|
|
315
|
+
*
|
|
316
|
+
* // Premium mode (best quality)
|
|
317
|
+
* const result = await client.smartChat('Write a business plan', { routingProfile: 'premium' });
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
smartChat(prompt: string, options?: SmartChatOptions): Promise<SmartChatResponse>;
|
|
321
|
+
/**
|
|
322
|
+
* Get model pricing map (cached).
|
|
323
|
+
* Fetches from API on first call, then returns cached result.
|
|
324
|
+
*/
|
|
325
|
+
private getModelPricing;
|
|
326
|
+
/**
|
|
327
|
+
* Fetch model pricing from API.
|
|
328
|
+
*/
|
|
329
|
+
private fetchModelPricing;
|
|
210
330
|
/**
|
|
211
331
|
* Full chat completion interface (OpenAI-compatible).
|
|
212
332
|
*
|
|
@@ -266,7 +386,38 @@ declare class LLMClient {
|
|
|
266
386
|
* Get the wallet address being used for payments.
|
|
267
387
|
*/
|
|
268
388
|
getWalletAddress(): string;
|
|
389
|
+
/**
|
|
390
|
+
* Check if client is configured for testnet.
|
|
391
|
+
*/
|
|
392
|
+
isTestnet(): boolean;
|
|
269
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* Create a testnet LLM client for development and testing.
|
|
396
|
+
*
|
|
397
|
+
* This is a convenience function that creates an LLMClient configured
|
|
398
|
+
* for the BlockRun testnet (Base Sepolia).
|
|
399
|
+
*
|
|
400
|
+
* @param options - Client options (privateKey required unless BASE_CHAIN_WALLET_KEY env var is set)
|
|
401
|
+
* @returns LLMClient configured for testnet
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* ```ts
|
|
405
|
+
* import { testnetClient } from '@blockrun/llm';
|
|
406
|
+
*
|
|
407
|
+
* const client = testnetClient({ privateKey: '0x...' });
|
|
408
|
+
* const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
|
|
409
|
+
* ```
|
|
410
|
+
*
|
|
411
|
+
* Testnet Setup:
|
|
412
|
+
* 1. Get testnet ETH from https://www.alchemy.com/faucets/base-sepolia
|
|
413
|
+
* 2. Get testnet USDC from https://faucet.circle.com/
|
|
414
|
+
* 3. Use your wallet with testnet funds
|
|
415
|
+
*
|
|
416
|
+
* Available Testnet Models:
|
|
417
|
+
* - openai/gpt-oss-20b
|
|
418
|
+
* - openai/gpt-oss-120b
|
|
419
|
+
*/
|
|
420
|
+
declare function testnetClient(options?: Omit<LLMClientOptions, 'apiUrl'>): LLMClient;
|
|
270
421
|
|
|
271
422
|
/**
|
|
272
423
|
* BlockRun Image Client - Generate images via x402 micropayments.
|
|
@@ -485,8 +636,11 @@ interface OpenAIClientOptions {
|
|
|
485
636
|
interface OpenAIChatCompletionParams {
|
|
486
637
|
model: string;
|
|
487
638
|
messages: Array<{
|
|
488
|
-
role: "system" | "user" | "assistant";
|
|
489
|
-
content
|
|
639
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
640
|
+
content?: string | null;
|
|
641
|
+
name?: string;
|
|
642
|
+
tool_call_id?: string;
|
|
643
|
+
tool_calls?: ToolCall[];
|
|
490
644
|
}>;
|
|
491
645
|
max_tokens?: number;
|
|
492
646
|
temperature?: number;
|
|
@@ -497,14 +651,17 @@ interface OpenAIChatCompletionParams {
|
|
|
497
651
|
presence_penalty?: number;
|
|
498
652
|
frequency_penalty?: number;
|
|
499
653
|
user?: string;
|
|
654
|
+
tools?: Tool[];
|
|
655
|
+
tool_choice?: ToolChoice;
|
|
500
656
|
}
|
|
501
657
|
interface OpenAIChatCompletionChoice {
|
|
502
658
|
index: number;
|
|
503
659
|
message: {
|
|
504
660
|
role: "assistant";
|
|
505
|
-
content
|
|
661
|
+
content?: string | null;
|
|
662
|
+
tool_calls?: ToolCall[];
|
|
506
663
|
};
|
|
507
|
-
finish_reason:
|
|
664
|
+
finish_reason: "stop" | "length" | "content_filter" | "tool_calls" | null;
|
|
508
665
|
}
|
|
509
666
|
interface OpenAIChatCompletionResponse {
|
|
510
667
|
id: string;
|
|
@@ -584,4 +741,4 @@ declare class OpenAI {
|
|
|
584
741
|
getWalletAddress(): string;
|
|
585
742
|
}
|
|
586
743
|
|
|
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 };
|
|
744
|
+
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 RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, type SearchParameters, type SearchSource, type SmartChatOptions, type SmartChatResponse, 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.js
CHANGED
|
@@ -27,6 +27,9 @@ var APIError = class extends BlockrunError {
|
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
// src/client.ts
|
|
31
|
+
import { route, DEFAULT_ROUTING_CONFIG } from "@blockrun/clawrouter";
|
|
32
|
+
|
|
30
33
|
// src/x402.ts
|
|
31
34
|
import { signTypedData } from "viem/accounts";
|
|
32
35
|
var BASE_CHAIN_ID = 8453;
|
|
@@ -223,15 +226,22 @@ function validateResourceUrl(url, baseUrl) {
|
|
|
223
226
|
|
|
224
227
|
// src/client.ts
|
|
225
228
|
var DEFAULT_API_URL = "https://blockrun.ai/api";
|
|
229
|
+
var TESTNET_API_URL = "https://testnet.blockrun.ai/api";
|
|
226
230
|
var DEFAULT_MAX_TOKENS = 1024;
|
|
227
231
|
var DEFAULT_TIMEOUT = 6e4;
|
|
232
|
+
var SDK_VERSION = "0.3.0";
|
|
233
|
+
var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
|
|
228
234
|
var LLMClient = class {
|
|
235
|
+
static DEFAULT_API_URL = DEFAULT_API_URL;
|
|
236
|
+
static TESTNET_API_URL = TESTNET_API_URL;
|
|
229
237
|
account;
|
|
230
238
|
privateKey;
|
|
231
239
|
apiUrl;
|
|
232
240
|
timeout;
|
|
233
241
|
sessionTotalUsd = 0;
|
|
234
242
|
sessionCalls = 0;
|
|
243
|
+
modelPricingCache = null;
|
|
244
|
+
modelPricingPromise = null;
|
|
235
245
|
/**
|
|
236
246
|
* Initialize the BlockRun LLM client.
|
|
237
247
|
*
|
|
@@ -278,7 +288,92 @@ var LLMClient = class {
|
|
|
278
288
|
search: options?.search,
|
|
279
289
|
searchParameters: options?.searchParameters
|
|
280
290
|
});
|
|
281
|
-
return result.choices[0].message.content;
|
|
291
|
+
return result.choices[0].message.content || "";
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Smart chat with automatic model routing.
|
|
295
|
+
*
|
|
296
|
+
* Uses ClawRouter's 14-dimension rule-based scoring algorithm (<1ms, 100% local)
|
|
297
|
+
* to select the cheapest model that can handle your request.
|
|
298
|
+
*
|
|
299
|
+
* @param prompt - User message
|
|
300
|
+
* @param options - Optional chat and routing parameters
|
|
301
|
+
* @returns SmartChatResponse with response text, selected model, and routing metadata
|
|
302
|
+
*
|
|
303
|
+
* @example Simple usage (auto profile)
|
|
304
|
+
* ```ts
|
|
305
|
+
* const result = await client.smartChat('What is 2+2?');
|
|
306
|
+
* console.log(result.response); // '4'
|
|
307
|
+
* console.log(result.model); // 'google/gemini-2.5-flash'
|
|
308
|
+
* console.log(result.routing.savings); // 0.78 (78% savings)
|
|
309
|
+
* ```
|
|
310
|
+
*
|
|
311
|
+
* @example With routing profile
|
|
312
|
+
* ```ts
|
|
313
|
+
* // Free tier only (zero cost)
|
|
314
|
+
* const result = await client.smartChat('Hello!', { routingProfile: 'free' });
|
|
315
|
+
*
|
|
316
|
+
* // Eco mode (budget optimized)
|
|
317
|
+
* const result = await client.smartChat('Explain quantum computing', { routingProfile: 'eco' });
|
|
318
|
+
*
|
|
319
|
+
* // Premium mode (best quality)
|
|
320
|
+
* const result = await client.smartChat('Write a business plan', { routingProfile: 'premium' });
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
async smartChat(prompt, options) {
|
|
324
|
+
const modelPricing = await this.getModelPricing();
|
|
325
|
+
const maxOutputTokens = options?.maxOutputTokens || options?.maxTokens || 1024;
|
|
326
|
+
const decision = route(prompt, options?.system, maxOutputTokens, {
|
|
327
|
+
config: DEFAULT_ROUTING_CONFIG,
|
|
328
|
+
modelPricing,
|
|
329
|
+
routingProfile: options?.routingProfile
|
|
330
|
+
});
|
|
331
|
+
const response = await this.chat(decision.model, prompt, {
|
|
332
|
+
system: options?.system,
|
|
333
|
+
maxTokens: options?.maxTokens,
|
|
334
|
+
temperature: options?.temperature,
|
|
335
|
+
topP: options?.topP,
|
|
336
|
+
search: options?.search,
|
|
337
|
+
searchParameters: options?.searchParameters
|
|
338
|
+
});
|
|
339
|
+
return {
|
|
340
|
+
response,
|
|
341
|
+
model: decision.model,
|
|
342
|
+
routing: decision
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Get model pricing map (cached).
|
|
347
|
+
* Fetches from API on first call, then returns cached result.
|
|
348
|
+
*/
|
|
349
|
+
async getModelPricing() {
|
|
350
|
+
if (this.modelPricingCache) {
|
|
351
|
+
return this.modelPricingCache;
|
|
352
|
+
}
|
|
353
|
+
if (this.modelPricingPromise) {
|
|
354
|
+
return this.modelPricingPromise;
|
|
355
|
+
}
|
|
356
|
+
this.modelPricingPromise = this.fetchModelPricing();
|
|
357
|
+
try {
|
|
358
|
+
this.modelPricingCache = await this.modelPricingPromise;
|
|
359
|
+
return this.modelPricingCache;
|
|
360
|
+
} finally {
|
|
361
|
+
this.modelPricingPromise = null;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Fetch model pricing from API.
|
|
366
|
+
*/
|
|
367
|
+
async fetchModelPricing() {
|
|
368
|
+
const models = await this.listModels();
|
|
369
|
+
const pricing = /* @__PURE__ */ new Map();
|
|
370
|
+
for (const model of models) {
|
|
371
|
+
pricing.set(model.id, {
|
|
372
|
+
inputPrice: model.inputPrice,
|
|
373
|
+
outputPrice: model.outputPrice
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
return pricing;
|
|
282
377
|
}
|
|
283
378
|
/**
|
|
284
379
|
* Full chat completion interface (OpenAI-compatible).
|
|
@@ -305,6 +400,12 @@ var LLMClient = class {
|
|
|
305
400
|
} else if (options?.search === true) {
|
|
306
401
|
body.search_parameters = { mode: "on" };
|
|
307
402
|
}
|
|
403
|
+
if (options?.tools !== void 0) {
|
|
404
|
+
body.tools = options.tools;
|
|
405
|
+
}
|
|
406
|
+
if (options?.toolChoice !== void 0) {
|
|
407
|
+
body.tool_choice = options.toolChoice;
|
|
408
|
+
}
|
|
308
409
|
return this.requestWithPayment("/v1/chat/completions", body);
|
|
309
410
|
}
|
|
310
411
|
/**
|
|
@@ -314,7 +415,7 @@ var LLMClient = class {
|
|
|
314
415
|
const url = `${this.apiUrl}${endpoint}`;
|
|
315
416
|
const response = await this.fetchWithTimeout(url, {
|
|
316
417
|
method: "POST",
|
|
317
|
-
headers: { "Content-Type": "application/json" },
|
|
418
|
+
headers: { "Content-Type": "application/json", "User-Agent": USER_AGENT },
|
|
318
419
|
body: JSON.stringify(body)
|
|
319
420
|
});
|
|
320
421
|
if (response.status === 402) {
|
|
@@ -377,6 +478,7 @@ var LLMClient = class {
|
|
|
377
478
|
method: "POST",
|
|
378
479
|
headers: {
|
|
379
480
|
"Content-Type": "application/json",
|
|
481
|
+
"User-Agent": USER_AGENT,
|
|
380
482
|
"PAYMENT-SIGNATURE": paymentPayload
|
|
381
483
|
},
|
|
382
484
|
body: JSON.stringify(body)
|
|
@@ -505,7 +607,19 @@ var LLMClient = class {
|
|
|
505
607
|
getWalletAddress() {
|
|
506
608
|
return this.account.address;
|
|
507
609
|
}
|
|
610
|
+
/**
|
|
611
|
+
* Check if client is configured for testnet.
|
|
612
|
+
*/
|
|
613
|
+
isTestnet() {
|
|
614
|
+
return this.apiUrl.includes("testnet.blockrun.ai");
|
|
615
|
+
}
|
|
508
616
|
};
|
|
617
|
+
function testnetClient(options = {}) {
|
|
618
|
+
return new LLMClient({
|
|
619
|
+
...options,
|
|
620
|
+
apiUrl: TESTNET_API_URL
|
|
621
|
+
});
|
|
622
|
+
}
|
|
509
623
|
var client_default = LLMClient;
|
|
510
624
|
|
|
511
625
|
// src/image.ts
|
|
@@ -907,7 +1021,9 @@ var ChatCompletions = class {
|
|
|
907
1021
|
{
|
|
908
1022
|
maxTokens: params.max_tokens,
|
|
909
1023
|
temperature: params.temperature,
|
|
910
|
-
topP: params.top_p
|
|
1024
|
+
topP: params.top_p,
|
|
1025
|
+
tools: params.tools,
|
|
1026
|
+
toolChoice: params.tool_choice
|
|
911
1027
|
}
|
|
912
1028
|
);
|
|
913
1029
|
return this.transformResponse(response);
|
|
@@ -922,6 +1038,12 @@ var ChatCompletions = class {
|
|
|
922
1038
|
top_p: params.top_p,
|
|
923
1039
|
stream: true
|
|
924
1040
|
};
|
|
1041
|
+
if (params.tools) {
|
|
1042
|
+
body.tools = params.tools;
|
|
1043
|
+
}
|
|
1044
|
+
if (params.tool_choice) {
|
|
1045
|
+
body.tool_choice = params.tool_choice;
|
|
1046
|
+
}
|
|
925
1047
|
const controller = new AbortController();
|
|
926
1048
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
927
1049
|
try {
|
|
@@ -958,7 +1080,8 @@ var ChatCompletions = class {
|
|
|
958
1080
|
index: choice.index ?? index,
|
|
959
1081
|
message: {
|
|
960
1082
|
role: "assistant",
|
|
961
|
-
content: choice.message.content
|
|
1083
|
+
content: choice.message.content,
|
|
1084
|
+
tool_calls: choice.message.tool_calls
|
|
962
1085
|
},
|
|
963
1086
|
finish_reason: choice.finish_reason || "stop"
|
|
964
1087
|
})),
|
|
@@ -1015,5 +1138,6 @@ export {
|
|
|
1015
1138
|
getPaymentLinks,
|
|
1016
1139
|
getWalletAddress,
|
|
1017
1140
|
loadWallet,
|
|
1018
|
-
saveWallet
|
|
1141
|
+
saveWallet,
|
|
1142
|
+
testnetClient
|
|
1019
1143
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/llm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "BlockRun LLM Gateway SDK - Pay-per-request AI via x402 on Base",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"url": "https://github.com/BlockRunAI/blockrun-llm-ts/issues"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
+
"@blockrun/clawrouter": "^0.9.3",
|
|
51
52
|
"viem": "^2.21.0"
|
|
52
53
|
},
|
|
53
54
|
"optionalDependencies": {
|