@blockrun/llm 1.3.1 → 1.4.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 +165 -5
- package/dist/index.cjs +121 -10
- package/dist/index.d.cts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +110 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -5,12 +5,16 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@blockrun/llm)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
## Supported Chains
|
|
9
|
+
|
|
10
|
+
| Chain | Network | Payment | Status |
|
|
11
|
+
|-------|---------|---------|--------|
|
|
12
|
+
| **Base** | Base Mainnet (Chain ID: 8453) | USDC | Primary |
|
|
13
|
+
| **Base Testnet** | Base Sepolia (Chain ID: 84532) | Testnet USDC | Development |
|
|
14
|
+
| **Solana** | Solana Mainnet | USDC (SPL) | New |
|
|
15
|
+
|
|
16
|
+
> **XRPL (RLUSD):** Use [@blockrun/llm-xrpl](https://www.npmjs.com/package/@blockrun/llm-xrpl) for XRPL payments
|
|
12
17
|
|
|
13
|
-
**Payment:** USDC
|
|
14
18
|
**Protocol:** x402 v2 (CDP Facilitator)
|
|
15
19
|
|
|
16
20
|
## Installation
|
|
@@ -87,6 +91,64 @@ const tweet = await client.chat('xai/grok-3-mini', 'What is trending on X?', { s
|
|
|
87
91
|
|
|
88
92
|
**Your private key never leaves your machine** - it's only used for local signing.
|
|
89
93
|
|
|
94
|
+
## Smart Routing (ClawRouter)
|
|
95
|
+
|
|
96
|
+
Let the SDK automatically pick the cheapest capable model for each request:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { LLMClient } from '@blockrun/llm';
|
|
100
|
+
|
|
101
|
+
const client = new LLMClient();
|
|
102
|
+
|
|
103
|
+
// Auto-routes to cheapest capable model
|
|
104
|
+
const result = await client.smartChat('What is 2+2?');
|
|
105
|
+
console.log(result.response); // '4'
|
|
106
|
+
console.log(result.model); // 'nvidia/kimi-k2.5' (cheap, fast)
|
|
107
|
+
console.log(`Saved ${(result.routing.savings * 100).toFixed(0)}%`); // 'Saved 78%'
|
|
108
|
+
|
|
109
|
+
// Complex reasoning task -> routes to reasoning model
|
|
110
|
+
const complex = await client.smartChat('Prove the Riemann hypothesis step by step');
|
|
111
|
+
console.log(complex.model); // 'xai/grok-4-1-fast-reasoning'
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Routing Profiles
|
|
115
|
+
|
|
116
|
+
| Profile | Description | Best For |
|
|
117
|
+
|---------|-------------|----------|
|
|
118
|
+
| `free` | nvidia/gpt-oss-120b only (FREE) | Testing, development |
|
|
119
|
+
| `eco` | Cheapest models per tier (DeepSeek, xAI) | Cost-sensitive production |
|
|
120
|
+
| `auto` | Best balance of cost/quality (default) | General use |
|
|
121
|
+
| `premium` | Top-tier models (OpenAI, Anthropic) | Quality-critical tasks |
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Use premium models for complex tasks
|
|
125
|
+
const result = await client.smartChat(
|
|
126
|
+
'Write production-grade async TypeScript code',
|
|
127
|
+
{ routingProfile: 'premium' }
|
|
128
|
+
);
|
|
129
|
+
console.log(result.model); // 'anthropic/claude-opus-4.5'
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### How ClawRouter Works
|
|
133
|
+
|
|
134
|
+
ClawRouter uses a 14-dimension rule-based classifier to analyze each request:
|
|
135
|
+
|
|
136
|
+
- **Token count** - Short vs long prompts
|
|
137
|
+
- **Code presence** - Programming keywords
|
|
138
|
+
- **Reasoning markers** - "prove", "step by step", etc.
|
|
139
|
+
- **Technical terms** - Architecture, optimization, etc.
|
|
140
|
+
- **Creative markers** - Story, poem, brainstorm, etc.
|
|
141
|
+
- **Agentic patterns** - Multi-step, tool use indicators
|
|
142
|
+
|
|
143
|
+
The classifier runs in <1ms, 100% locally, and routes to one of four tiers:
|
|
144
|
+
|
|
145
|
+
| Tier | Example Tasks | Auto Profile Model |
|
|
146
|
+
|------|---------------|-------------------|
|
|
147
|
+
| SIMPLE | "What is 2+2?", definitions | nvidia/kimi-k2.5 |
|
|
148
|
+
| MEDIUM | Code snippets, explanations | xai/grok-code-fast-1 |
|
|
149
|
+
| COMPLEX | Architecture, long documents | google/gemini-3.1-pro |
|
|
150
|
+
| REASONING | Proofs, multi-step reasoning | xai/grok-4-1-fast-reasoning |
|
|
151
|
+
|
|
90
152
|
## Available Models
|
|
91
153
|
|
|
92
154
|
### OpenAI GPT-5 Family
|
|
@@ -203,6 +265,78 @@ All models below have been tested end-to-end via the TypeScript SDK (Feb 2026):
|
|
|
203
265
|
|
|
204
266
|
*Testnet models use flat pricing (no token counting) for simplicity.*
|
|
205
267
|
|
|
268
|
+
## X/Twitter Data (Powered by AttentionVC)
|
|
269
|
+
|
|
270
|
+
Access X/Twitter user profiles, followers, and followings via [AttentionVC](https://attentionvc.ai) partner API. No API keys needed — pay-per-request via x402.
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
import { LLMClient } from '@blockrun/llm';
|
|
274
|
+
|
|
275
|
+
const client = new LLMClient();
|
|
276
|
+
|
|
277
|
+
// Look up user profiles ($0.002/user, min $0.02)
|
|
278
|
+
const users = await client.xUserLookup(['elonmusk', 'blockaborr']);
|
|
279
|
+
for (const user of users.users) {
|
|
280
|
+
console.log(`@${user.userName}: ${user.followers} followers`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Get followers ($0.05/page, ~200 accounts)
|
|
284
|
+
let result = await client.xFollowers('blockaborr');
|
|
285
|
+
for (const f of result.followers) {
|
|
286
|
+
console.log(` @${f.screen_name}`);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Paginate through all followers
|
|
290
|
+
while (result.has_next_page) {
|
|
291
|
+
result = await client.xFollowers('blockaborr', result.next_cursor);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Get followings ($0.05/page)
|
|
295
|
+
const followings = await client.xFollowings('blockaborr');
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Works on both `LLMClient` (Base) and `SolanaLLMClient`.
|
|
299
|
+
|
|
300
|
+
## Standalone Search
|
|
301
|
+
|
|
302
|
+
Search web, X/Twitter, and news without using a chat model:
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
import { LLMClient } from '@blockrun/llm';
|
|
306
|
+
|
|
307
|
+
const client = new LLMClient();
|
|
308
|
+
|
|
309
|
+
const result = await client.search('latest AI agent frameworks 2026');
|
|
310
|
+
console.log(result.summary);
|
|
311
|
+
for (const cite of result.citations ?? []) {
|
|
312
|
+
console.log(` - ${cite}`);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Filter by source type and date range
|
|
316
|
+
const filtered = await client.search('BlockRun x402', {
|
|
317
|
+
sources: ['web', 'x'],
|
|
318
|
+
fromDate: '2026-01-01',
|
|
319
|
+
maxResults: 5,
|
|
320
|
+
});
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Image Editing (img2img)
|
|
324
|
+
|
|
325
|
+
Edit existing images with text prompts:
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import { LLMClient } from '@blockrun/llm';
|
|
329
|
+
|
|
330
|
+
const client = new LLMClient();
|
|
331
|
+
|
|
332
|
+
const result = await client.imageEdit(
|
|
333
|
+
'Make the sky purple and add northern lights',
|
|
334
|
+
'data:image/png;base64,...', // base64 or URL
|
|
335
|
+
{ model: 'openai/gpt-image-1' }
|
|
336
|
+
);
|
|
337
|
+
console.log(result.data[0].url);
|
|
338
|
+
```
|
|
339
|
+
|
|
206
340
|
## Testnet Usage
|
|
207
341
|
|
|
208
342
|
For development and testing without real USDC, use the testnet:
|
|
@@ -636,6 +770,32 @@ console.log(`Calls: ${summary.calls}`);
|
|
|
636
770
|
console.log(`By model:`, summary.byModel);
|
|
637
771
|
```
|
|
638
772
|
|
|
773
|
+
## Anthropic SDK Compatibility
|
|
774
|
+
|
|
775
|
+
Use the official Anthropic SDK interface with BlockRun's pay-per-request backend:
|
|
776
|
+
|
|
777
|
+
```typescript
|
|
778
|
+
import { AnthropicClient } from '@blockrun/llm';
|
|
779
|
+
|
|
780
|
+
const client = new AnthropicClient(); // Auto-detects wallet, auto-pays
|
|
781
|
+
|
|
782
|
+
const response = await client.messages.create({
|
|
783
|
+
model: 'claude-sonnet-4-6',
|
|
784
|
+
max_tokens: 1024,
|
|
785
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
786
|
+
});
|
|
787
|
+
console.log(response.content[0].text);
|
|
788
|
+
|
|
789
|
+
// Any model works in Anthropic format
|
|
790
|
+
const gptResponse = await client.messages.create({
|
|
791
|
+
model: 'openai/gpt-5.4',
|
|
792
|
+
max_tokens: 1024,
|
|
793
|
+
messages: [{ role: 'user', content: 'Hello from GPT!' }],
|
|
794
|
+
});
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
The `AnthropicClient` wraps the official `@anthropic-ai/sdk` with a custom fetch that handles x402 payment automatically. Your private key never leaves your machine.
|
|
798
|
+
|
|
639
799
|
## Links
|
|
640
800
|
|
|
641
801
|
- [Website](https://blockrun.ai)
|
package/dist/index.cjs
CHANGED
|
@@ -11119,7 +11119,7 @@ function exportNodeCompatibleHeaders(headers) {
|
|
|
11119
11119
|
return obj;
|
|
11120
11120
|
}
|
|
11121
11121
|
function createHeadersLenient(obj) {
|
|
11122
|
-
const headers = new
|
|
11122
|
+
const headers = new Headers2();
|
|
11123
11123
|
for (const name of Object.keys(obj)) {
|
|
11124
11124
|
if (invalidTokenRegex.test(name)) {
|
|
11125
11125
|
continue;
|
|
@@ -11156,7 +11156,7 @@ function isAbortSignal(signal) {
|
|
|
11156
11156
|
}
|
|
11157
11157
|
function getNodeRequestOptions(request) {
|
|
11158
11158
|
const parsedURL = request[INTERNALS$2].parsedURL;
|
|
11159
|
-
const headers = new
|
|
11159
|
+
const headers = new Headers2(request[INTERNALS$2].headers);
|
|
11160
11160
|
if (!headers.has("Accept")) {
|
|
11161
11161
|
headers.set("Accept", "*/*");
|
|
11162
11162
|
}
|
|
@@ -11316,7 +11316,7 @@ function fetch2(url2, opts) {
|
|
|
11316
11316
|
return;
|
|
11317
11317
|
}
|
|
11318
11318
|
const requestOpts = {
|
|
11319
|
-
headers: new
|
|
11319
|
+
headers: new Headers2(request.headers),
|
|
11320
11320
|
follow: request.follow,
|
|
11321
11321
|
counter: request.counter + 1,
|
|
11322
11322
|
agent: request.agent,
|
|
@@ -11434,7 +11434,7 @@ function destroyStream(stream, err) {
|
|
|
11434
11434
|
stream.end();
|
|
11435
11435
|
}
|
|
11436
11436
|
}
|
|
11437
|
-
var import_stream, import_http, import_url, import_whatwg_url, import_https, import_zlib, Readable, BUFFER, TYPE2, Blob2, convert, INTERNALS, PassThrough, invalidTokenRegex, invalidHeaderCharRegex, MAP,
|
|
11437
|
+
var import_stream, import_http, import_url, import_whatwg_url, import_https, import_zlib, Readable, BUFFER, TYPE2, Blob2, convert, INTERNALS, PassThrough, invalidTokenRegex, invalidHeaderCharRegex, MAP, Headers2, INTERNAL, HeadersIteratorPrototype, INTERNALS$1, STATUS_CODES, Response, INTERNALS$2, URL3, parse_url, format_url, streamDestructionSupported, Request, URL$1, PassThrough$1, isDomainOrSubdomain, isSameProtocol, lib_default;
|
|
11438
11438
|
var init_lib = __esm({
|
|
11439
11439
|
"node_modules/.pnpm/node-fetch@2.7.0/node_modules/node-fetch/lib/index.mjs"() {
|
|
11440
11440
|
"use strict";
|
|
@@ -11655,7 +11655,7 @@ var init_lib = __esm({
|
|
|
11655
11655
|
invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/;
|
|
11656
11656
|
invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
|
|
11657
11657
|
MAP = /* @__PURE__ */ Symbol("map");
|
|
11658
|
-
|
|
11658
|
+
Headers2 = class _Headers {
|
|
11659
11659
|
/**
|
|
11660
11660
|
* Headers class
|
|
11661
11661
|
*
|
|
@@ -11833,14 +11833,14 @@ var init_lib = __esm({
|
|
|
11833
11833
|
return createHeadersIterator(this, "key+value");
|
|
11834
11834
|
}
|
|
11835
11835
|
};
|
|
11836
|
-
|
|
11837
|
-
Object.defineProperty(
|
|
11836
|
+
Headers2.prototype.entries = Headers2.prototype[Symbol.iterator];
|
|
11837
|
+
Object.defineProperty(Headers2.prototype, Symbol.toStringTag, {
|
|
11838
11838
|
value: "Headers",
|
|
11839
11839
|
writable: false,
|
|
11840
11840
|
enumerable: false,
|
|
11841
11841
|
configurable: true
|
|
11842
11842
|
});
|
|
11843
|
-
Object.defineProperties(
|
|
11843
|
+
Object.defineProperties(Headers2.prototype, {
|
|
11844
11844
|
get: { enumerable: true },
|
|
11845
11845
|
forEach: { enumerable: true },
|
|
11846
11846
|
set: { enumerable: true },
|
|
@@ -11888,7 +11888,7 @@ var init_lib = __esm({
|
|
|
11888
11888
|
let opts = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
11889
11889
|
Body.call(this, body, opts);
|
|
11890
11890
|
const status2 = opts.status || 200;
|
|
11891
|
-
const headers = new
|
|
11891
|
+
const headers = new Headers2(opts.headers);
|
|
11892
11892
|
if (body != null && !headers.has("Content-Type")) {
|
|
11893
11893
|
const contentType = extractContentType(body);
|
|
11894
11894
|
if (contentType) {
|
|
@@ -11985,7 +11985,7 @@ var init_lib = __esm({
|
|
|
11985
11985
|
timeout: init.timeout || input.timeout || 0,
|
|
11986
11986
|
size: init.size || input.size || 0
|
|
11987
11987
|
});
|
|
11988
|
-
const headers = new
|
|
11988
|
+
const headers = new Headers2(init.headers || input.headers || {});
|
|
11989
11989
|
if (inputBody != null && !headers.has("Content-Type")) {
|
|
11990
11990
|
const contentType = extractContentType(inputBody);
|
|
11991
11991
|
if (contentType) {
|
|
@@ -36420,6 +36420,7 @@ var init_esm4 = __esm({
|
|
|
36420
36420
|
var index_exports = {};
|
|
36421
36421
|
__export(index_exports, {
|
|
36422
36422
|
APIError: () => APIError,
|
|
36423
|
+
AnthropicClient: () => AnthropicClient,
|
|
36423
36424
|
BASE_CHAIN_ID: () => BASE_CHAIN_ID,
|
|
36424
36425
|
BlockrunError: () => BlockrunError,
|
|
36425
36426
|
ImageClient: () => ImageClient,
|
|
@@ -39016,9 +39017,119 @@ var OpenAI = class {
|
|
|
39016
39017
|
return this.client.getWalletAddress();
|
|
39017
39018
|
}
|
|
39018
39019
|
};
|
|
39020
|
+
|
|
39021
|
+
// src/anthropic-compat.ts
|
|
39022
|
+
var import_accounts5 = require("viem/accounts");
|
|
39023
|
+
var AnthropicClient = class {
|
|
39024
|
+
_client = null;
|
|
39025
|
+
_clientPromise = null;
|
|
39026
|
+
_privateKey;
|
|
39027
|
+
_account;
|
|
39028
|
+
_apiUrl;
|
|
39029
|
+
_timeout;
|
|
39030
|
+
constructor(options = {}) {
|
|
39031
|
+
const wallet = getOrCreateWallet();
|
|
39032
|
+
const key = options.privateKey ?? wallet.privateKey;
|
|
39033
|
+
validatePrivateKey(key);
|
|
39034
|
+
this._privateKey = key;
|
|
39035
|
+
this._account = (0, import_accounts5.privateKeyToAccount)(this._privateKey);
|
|
39036
|
+
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
39037
|
+
validateApiUrl(apiUrl);
|
|
39038
|
+
this._apiUrl = apiUrl.replace(/\/$/, "");
|
|
39039
|
+
this._timeout = options.timeout ?? 6e4;
|
|
39040
|
+
}
|
|
39041
|
+
async _getClient() {
|
|
39042
|
+
if (this._client) return this._client;
|
|
39043
|
+
if (this._clientPromise) return this._clientPromise;
|
|
39044
|
+
this._clientPromise = (async () => {
|
|
39045
|
+
const { default: Anthropic } = await import("@anthropic-ai/sdk");
|
|
39046
|
+
this._client = new Anthropic({
|
|
39047
|
+
baseURL: this._apiUrl,
|
|
39048
|
+
apiKey: "blockrun",
|
|
39049
|
+
fetch: this._x402Fetch.bind(this)
|
|
39050
|
+
});
|
|
39051
|
+
return this._client;
|
|
39052
|
+
})();
|
|
39053
|
+
return this._clientPromise;
|
|
39054
|
+
}
|
|
39055
|
+
async _x402Fetch(input, init) {
|
|
39056
|
+
const controller = new AbortController();
|
|
39057
|
+
const timeoutId = setTimeout(() => controller.abort(), this._timeout);
|
|
39058
|
+
try {
|
|
39059
|
+
const mergedInit = { ...init, signal: controller.signal };
|
|
39060
|
+
let response = await globalThis.fetch(input, mergedInit);
|
|
39061
|
+
if (response.status === 402) {
|
|
39062
|
+
let paymentHeader = response.headers.get("payment-required");
|
|
39063
|
+
if (!paymentHeader) {
|
|
39064
|
+
try {
|
|
39065
|
+
const respBody = await response.json();
|
|
39066
|
+
if (respBody.x402 || respBody.accepts) {
|
|
39067
|
+
paymentHeader = btoa(JSON.stringify(respBody));
|
|
39068
|
+
}
|
|
39069
|
+
} catch {
|
|
39070
|
+
}
|
|
39071
|
+
}
|
|
39072
|
+
if (!paymentHeader) {
|
|
39073
|
+
throw new Error("402 response but no payment requirements found");
|
|
39074
|
+
}
|
|
39075
|
+
const paymentRequired = parsePaymentRequired(paymentHeader);
|
|
39076
|
+
const details = extractPaymentDetails(paymentRequired);
|
|
39077
|
+
const extensions = paymentRequired.extensions;
|
|
39078
|
+
const paymentPayload = await createPaymentPayload(
|
|
39079
|
+
this._privateKey,
|
|
39080
|
+
this._account.address,
|
|
39081
|
+
details.recipient,
|
|
39082
|
+
details.amount,
|
|
39083
|
+
details.network || "eip155:8453",
|
|
39084
|
+
{
|
|
39085
|
+
resourceUrl: validateResourceUrl(
|
|
39086
|
+
details.resource?.url || `${this._apiUrl}/v1/messages`,
|
|
39087
|
+
this._apiUrl
|
|
39088
|
+
),
|
|
39089
|
+
resourceDescription: details.resource?.description || "BlockRun AI API call",
|
|
39090
|
+
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
39091
|
+
extra: details.extra,
|
|
39092
|
+
extensions
|
|
39093
|
+
}
|
|
39094
|
+
);
|
|
39095
|
+
const newHeaders = new Headers(init?.headers);
|
|
39096
|
+
newHeaders.set("PAYMENT-SIGNATURE", paymentPayload);
|
|
39097
|
+
response = await globalThis.fetch(input, {
|
|
39098
|
+
...init,
|
|
39099
|
+
headers: newHeaders,
|
|
39100
|
+
signal: controller.signal
|
|
39101
|
+
});
|
|
39102
|
+
if (response.status === 402) {
|
|
39103
|
+
throw new Error(
|
|
39104
|
+
"Payment was rejected. Check your wallet balance."
|
|
39105
|
+
);
|
|
39106
|
+
}
|
|
39107
|
+
}
|
|
39108
|
+
return response;
|
|
39109
|
+
} finally {
|
|
39110
|
+
clearTimeout(timeoutId);
|
|
39111
|
+
}
|
|
39112
|
+
}
|
|
39113
|
+
get messages() {
|
|
39114
|
+
const handler = {
|
|
39115
|
+
get: (_target, prop) => {
|
|
39116
|
+
return async (...args) => {
|
|
39117
|
+
const client = await this._getClient();
|
|
39118
|
+
const messages = client.messages;
|
|
39119
|
+
return messages[prop](...args);
|
|
39120
|
+
};
|
|
39121
|
+
}
|
|
39122
|
+
};
|
|
39123
|
+
return new Proxy({}, handler);
|
|
39124
|
+
}
|
|
39125
|
+
getWalletAddress() {
|
|
39126
|
+
return this._account.address;
|
|
39127
|
+
}
|
|
39128
|
+
};
|
|
39019
39129
|
// Annotate the CommonJS export names for ESM import in node:
|
|
39020
39130
|
0 && (module.exports = {
|
|
39021
39131
|
APIError,
|
|
39132
|
+
AnthropicClient,
|
|
39022
39133
|
BASE_CHAIN_ID,
|
|
39023
39134
|
BlockrunError,
|
|
39024
39135
|
ImageClient,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as _anthropic_ai_sdk from '@anthropic-ai/sdk';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Type definitions for BlockRun LLM SDK
|
|
3
5
|
*/
|
|
@@ -1319,4 +1321,23 @@ declare class OpenAI {
|
|
|
1319
1321
|
getWalletAddress(): string;
|
|
1320
1322
|
}
|
|
1321
1323
|
|
|
1322
|
-
|
|
1324
|
+
interface BlockRunAnthropicOptions {
|
|
1325
|
+
privateKey?: `0x${string}` | string;
|
|
1326
|
+
apiUrl?: string;
|
|
1327
|
+
timeout?: number;
|
|
1328
|
+
}
|
|
1329
|
+
declare class AnthropicClient {
|
|
1330
|
+
private _client;
|
|
1331
|
+
private _clientPromise;
|
|
1332
|
+
private _privateKey;
|
|
1333
|
+
private _account;
|
|
1334
|
+
private _apiUrl;
|
|
1335
|
+
private _timeout;
|
|
1336
|
+
constructor(options?: BlockRunAnthropicOptions);
|
|
1337
|
+
private _getClient;
|
|
1338
|
+
private _x402Fetch;
|
|
1339
|
+
get messages(): _anthropic_ai_sdk.default['messages'];
|
|
1340
|
+
getWalletAddress(): string;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
export { APIError, AnthropicClient, BASE_CHAIN_ID, type BlockRunAnthropicOptions, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, type CostEntry, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, 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, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, type SearchOptions, type SearchParameters, type SearchResult, type SearchSource, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XArticlesRisingResponse, type XAuthorAnalyticsResponse, type XCompareAuthorsResponse, type XFollower, type XFollowersResponse, type XFollowingsResponse, type XMentionsResponse, type XSearchResponse, type XSearchSource, type XTrendingResponse, type XTweet, type XTweetLookupResponse, type XTweetRepliesResponse, type XTweetThreadResponse, type XTweetsResponse, type XUser, type XUserInfoResponse, type XUserLookupResponse, type XVerifiedFollowersResponse, clearCache, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getCached, getCachedByRequest, getCostSummary, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadSolanaWallet, loadWallet, logCost, saveSolanaWallet, saveToCache, saveWallet, scanSolanaWallets, scanWallets, setCache, setupAgentSolanaWallet, setupAgentWallet, solanaClient, solanaKeyToBytes, solanaPublicKey, status, testnetClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as _anthropic_ai_sdk from '@anthropic-ai/sdk';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Type definitions for BlockRun LLM SDK
|
|
3
5
|
*/
|
|
@@ -1319,4 +1321,23 @@ declare class OpenAI {
|
|
|
1319
1321
|
getWalletAddress(): string;
|
|
1320
1322
|
}
|
|
1321
1323
|
|
|
1322
|
-
|
|
1324
|
+
interface BlockRunAnthropicOptions {
|
|
1325
|
+
privateKey?: `0x${string}` | string;
|
|
1326
|
+
apiUrl?: string;
|
|
1327
|
+
timeout?: number;
|
|
1328
|
+
}
|
|
1329
|
+
declare class AnthropicClient {
|
|
1330
|
+
private _client;
|
|
1331
|
+
private _clientPromise;
|
|
1332
|
+
private _privateKey;
|
|
1333
|
+
private _account;
|
|
1334
|
+
private _apiUrl;
|
|
1335
|
+
private _timeout;
|
|
1336
|
+
constructor(options?: BlockRunAnthropicOptions);
|
|
1337
|
+
private _getClient;
|
|
1338
|
+
private _x402Fetch;
|
|
1339
|
+
get messages(): _anthropic_ai_sdk.default['messages'];
|
|
1340
|
+
getWalletAddress(): string;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
export { APIError, AnthropicClient, BASE_CHAIN_ID, type BlockRunAnthropicOptions, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, type CostEntry, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, 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, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, type SearchOptions, type SearchParameters, type SearchResult, type SearchSource, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XArticlesRisingResponse, type XAuthorAnalyticsResponse, type XCompareAuthorsResponse, type XFollower, type XFollowersResponse, type XFollowingsResponse, type XMentionsResponse, type XSearchResponse, type XSearchSource, type XTrendingResponse, type XTweet, type XTweetLookupResponse, type XTweetRepliesResponse, type XTweetThreadResponse, type XTweetsResponse, type XUser, type XUserInfoResponse, type XUserLookupResponse, type XVerifiedFollowersResponse, clearCache, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getCached, getCachedByRequest, getCostSummary, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadSolanaWallet, loadWallet, logCost, saveSolanaWallet, saveToCache, saveWallet, scanSolanaWallets, scanWallets, setCache, setupAgentSolanaWallet, setupAgentWallet, solanaClient, solanaKeyToBytes, solanaPublicKey, status, testnetClient };
|
package/dist/index.js
CHANGED
|
@@ -2552,8 +2552,118 @@ var OpenAI = class {
|
|
|
2552
2552
|
return this.client.getWalletAddress();
|
|
2553
2553
|
}
|
|
2554
2554
|
};
|
|
2555
|
+
|
|
2556
|
+
// src/anthropic-compat.ts
|
|
2557
|
+
import { privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
|
|
2558
|
+
var AnthropicClient = class {
|
|
2559
|
+
_client = null;
|
|
2560
|
+
_clientPromise = null;
|
|
2561
|
+
_privateKey;
|
|
2562
|
+
_account;
|
|
2563
|
+
_apiUrl;
|
|
2564
|
+
_timeout;
|
|
2565
|
+
constructor(options = {}) {
|
|
2566
|
+
const wallet = getOrCreateWallet();
|
|
2567
|
+
const key = options.privateKey ?? wallet.privateKey;
|
|
2568
|
+
validatePrivateKey(key);
|
|
2569
|
+
this._privateKey = key;
|
|
2570
|
+
this._account = privateKeyToAccount4(this._privateKey);
|
|
2571
|
+
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
2572
|
+
validateApiUrl(apiUrl);
|
|
2573
|
+
this._apiUrl = apiUrl.replace(/\/$/, "");
|
|
2574
|
+
this._timeout = options.timeout ?? 6e4;
|
|
2575
|
+
}
|
|
2576
|
+
async _getClient() {
|
|
2577
|
+
if (this._client) return this._client;
|
|
2578
|
+
if (this._clientPromise) return this._clientPromise;
|
|
2579
|
+
this._clientPromise = (async () => {
|
|
2580
|
+
const { default: Anthropic } = await import("@anthropic-ai/sdk");
|
|
2581
|
+
this._client = new Anthropic({
|
|
2582
|
+
baseURL: this._apiUrl,
|
|
2583
|
+
apiKey: "blockrun",
|
|
2584
|
+
fetch: this._x402Fetch.bind(this)
|
|
2585
|
+
});
|
|
2586
|
+
return this._client;
|
|
2587
|
+
})();
|
|
2588
|
+
return this._clientPromise;
|
|
2589
|
+
}
|
|
2590
|
+
async _x402Fetch(input, init) {
|
|
2591
|
+
const controller = new AbortController();
|
|
2592
|
+
const timeoutId = setTimeout(() => controller.abort(), this._timeout);
|
|
2593
|
+
try {
|
|
2594
|
+
const mergedInit = { ...init, signal: controller.signal };
|
|
2595
|
+
let response = await globalThis.fetch(input, mergedInit);
|
|
2596
|
+
if (response.status === 402) {
|
|
2597
|
+
let paymentHeader = response.headers.get("payment-required");
|
|
2598
|
+
if (!paymentHeader) {
|
|
2599
|
+
try {
|
|
2600
|
+
const respBody = await response.json();
|
|
2601
|
+
if (respBody.x402 || respBody.accepts) {
|
|
2602
|
+
paymentHeader = btoa(JSON.stringify(respBody));
|
|
2603
|
+
}
|
|
2604
|
+
} catch {
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
if (!paymentHeader) {
|
|
2608
|
+
throw new Error("402 response but no payment requirements found");
|
|
2609
|
+
}
|
|
2610
|
+
const paymentRequired = parsePaymentRequired(paymentHeader);
|
|
2611
|
+
const details = extractPaymentDetails(paymentRequired);
|
|
2612
|
+
const extensions = paymentRequired.extensions;
|
|
2613
|
+
const paymentPayload = await createPaymentPayload(
|
|
2614
|
+
this._privateKey,
|
|
2615
|
+
this._account.address,
|
|
2616
|
+
details.recipient,
|
|
2617
|
+
details.amount,
|
|
2618
|
+
details.network || "eip155:8453",
|
|
2619
|
+
{
|
|
2620
|
+
resourceUrl: validateResourceUrl(
|
|
2621
|
+
details.resource?.url || `${this._apiUrl}/v1/messages`,
|
|
2622
|
+
this._apiUrl
|
|
2623
|
+
),
|
|
2624
|
+
resourceDescription: details.resource?.description || "BlockRun AI API call",
|
|
2625
|
+
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
2626
|
+
extra: details.extra,
|
|
2627
|
+
extensions
|
|
2628
|
+
}
|
|
2629
|
+
);
|
|
2630
|
+
const newHeaders = new Headers(init?.headers);
|
|
2631
|
+
newHeaders.set("PAYMENT-SIGNATURE", paymentPayload);
|
|
2632
|
+
response = await globalThis.fetch(input, {
|
|
2633
|
+
...init,
|
|
2634
|
+
headers: newHeaders,
|
|
2635
|
+
signal: controller.signal
|
|
2636
|
+
});
|
|
2637
|
+
if (response.status === 402) {
|
|
2638
|
+
throw new Error(
|
|
2639
|
+
"Payment was rejected. Check your wallet balance."
|
|
2640
|
+
);
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
return response;
|
|
2644
|
+
} finally {
|
|
2645
|
+
clearTimeout(timeoutId);
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
get messages() {
|
|
2649
|
+
const handler = {
|
|
2650
|
+
get: (_target, prop) => {
|
|
2651
|
+
return async (...args) => {
|
|
2652
|
+
const client = await this._getClient();
|
|
2653
|
+
const messages = client.messages;
|
|
2654
|
+
return messages[prop](...args);
|
|
2655
|
+
};
|
|
2656
|
+
}
|
|
2657
|
+
};
|
|
2658
|
+
return new Proxy({}, handler);
|
|
2659
|
+
}
|
|
2660
|
+
getWalletAddress() {
|
|
2661
|
+
return this._account.address;
|
|
2662
|
+
}
|
|
2663
|
+
};
|
|
2555
2664
|
export {
|
|
2556
2665
|
APIError,
|
|
2666
|
+
AnthropicClient,
|
|
2557
2667
|
BASE_CHAIN_ID,
|
|
2558
2668
|
BlockrunError,
|
|
2559
2669
|
ImageClient,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/llm",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "BlockRun LLM Gateway SDK - Pay-per-request AI via x402 on Base and Solana",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"README.md"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
22
|
-
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
21
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean --external @anthropic-ai/sdk",
|
|
22
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch --external @anthropic-ai/sdk",
|
|
23
23
|
"test": "vitest",
|
|
24
24
|
"lint": "eslint src/",
|
|
25
25
|
"typecheck": "tsc --noEmit"
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"viem": "^2.21.0"
|
|
54
54
|
},
|
|
55
55
|
"optionalDependencies": {
|
|
56
|
+
"@anthropic-ai/sdk": "^0.39.0",
|
|
56
57
|
"@solana/spl-token": "^0.4.0",
|
|
57
58
|
"@solana/web3.js": "^1.98.0"
|
|
58
59
|
},
|