@blockrun/llm 1.6.1 → 1.7.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 +104 -1
- package/dist/index.cjs +168 -11
- package/dist/index.d.cts +153 -3
- package/dist/index.d.ts +153 -3
- package/dist/index.js +166 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @blockrun/llm (TypeScript SDK)
|
|
2
2
|
|
|
3
|
-
> **@blockrun/llm** is a TypeScript/Node.js SDK for accessing
|
|
3
|
+
> **@blockrun/llm** is a TypeScript/Node.js SDK for accessing 41+ large language models (GPT-5, Claude, Gemini, Grok, DeepSeek, Kimi, and more) with automatic pay-per-request USDC micropayments via the x402 protocol. No API keys required — your wallet signature is your authentication. Supports **streaming**, smart routing, Base and Solana chains.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@blockrun/llm)
|
|
6
6
|
[](LICENSE)
|
|
@@ -264,6 +264,28 @@ All models below have been tested end-to-end via the TypeScript SDK (Feb 2026):
|
|
|
264
264
|
| `google/nano-banana` | $0.05/image |
|
|
265
265
|
| `google/nano-banana-pro` | $0.10-0.15/image |
|
|
266
266
|
| `black-forest/flux-1.1-pro` | $0.04/image |
|
|
267
|
+
| `xai/grok-imagine-image` | $0.02/image |
|
|
268
|
+
| `xai/grok-imagine-image-pro` | $0.07/image |
|
|
269
|
+
| `zai/cogview-4` | $0.015/image |
|
|
270
|
+
|
|
271
|
+
### Video Generation
|
|
272
|
+
| Model | Price |
|
|
273
|
+
|-------|-------|
|
|
274
|
+
| `xai/grok-imagine-video` | $0.05/sec (8s default → $0.42/clip) |
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import { VideoClient } from '@blockrun/llm';
|
|
278
|
+
|
|
279
|
+
const client = new VideoClient();
|
|
280
|
+
const result = await client.generate('a red apple slowly spinning on a wooden table');
|
|
281
|
+
console.log(result.data[0].url); // permanent MP4 URL
|
|
282
|
+
console.log(result.data[0].duration_seconds); // 8
|
|
283
|
+
|
|
284
|
+
// Image-to-video
|
|
285
|
+
const r2 = await client.generate('the subject turns and smiles', {
|
|
286
|
+
imageUrl: 'https://example.com/portrait.jpg',
|
|
287
|
+
});
|
|
288
|
+
```
|
|
267
289
|
|
|
268
290
|
### Testnet Models (Base Sepolia)
|
|
269
291
|
| Model | Price |
|
|
@@ -462,6 +484,74 @@ const result = await client.chatCompletion('openai/gpt-4o', messages);
|
|
|
462
484
|
console.log(result.choices[0].message.content);
|
|
463
485
|
```
|
|
464
486
|
|
|
487
|
+
### Streaming
|
|
488
|
+
|
|
489
|
+
Stream responses token-by-token with automatic x402 payment. Uses a **pre-auth cache** to skip the 402 round-trip on repeat calls to the same model (~200ms saved per request after the first).
|
|
490
|
+
|
|
491
|
+
#### OpenAI-compatible (recommended)
|
|
492
|
+
|
|
493
|
+
```typescript
|
|
494
|
+
import { OpenAI } from '@blockrun/llm';
|
|
495
|
+
|
|
496
|
+
const client = new OpenAI({ walletKey: process.env.BASE_CHAIN_WALLET_KEY });
|
|
497
|
+
|
|
498
|
+
const stream = await client.chat.completions.create({
|
|
499
|
+
model: 'openai/gpt-5.4',
|
|
500
|
+
messages: [{ role: 'user', content: 'Write a short story about AI agents' }],
|
|
501
|
+
stream: true,
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
for await (const chunk of stream) {
|
|
505
|
+
process.stdout.write(chunk.choices[0]?.delta?.content || '');
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
#### Native client
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
import { LLMClient, type ChatMessage } from '@blockrun/llm';
|
|
513
|
+
|
|
514
|
+
const client = new LLMClient();
|
|
515
|
+
|
|
516
|
+
const messages: ChatMessage[] = [
|
|
517
|
+
{ role: 'user', content: 'Explain quantum computing in simple terms' },
|
|
518
|
+
];
|
|
519
|
+
|
|
520
|
+
// Returns a raw fetch Response with SSE body
|
|
521
|
+
const response = await client.chatCompletionStream('google/gemini-2.5-flash', messages);
|
|
522
|
+
|
|
523
|
+
const reader = response.body!.getReader();
|
|
524
|
+
const decoder = new TextDecoder();
|
|
525
|
+
|
|
526
|
+
while (true) {
|
|
527
|
+
const { done, value } = await reader.read();
|
|
528
|
+
if (done) break;
|
|
529
|
+
|
|
530
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
531
|
+
for (const line of chunk.split('\n')) {
|
|
532
|
+
if (!line.startsWith('data: ') || line === 'data: [DONE]') continue;
|
|
533
|
+
const data = JSON.parse(line.slice(6));
|
|
534
|
+
process.stdout.write(data.choices?.[0]?.delta?.content || '');
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
#### Payment + streaming flow
|
|
540
|
+
|
|
541
|
+
```
|
|
542
|
+
First call (cache miss):
|
|
543
|
+
1. Send request → 402 response (BlockRun returns price)
|
|
544
|
+
2. Sign USDC payment locally (key never leaves machine)
|
|
545
|
+
3. Retry with PAYMENT-SIGNATURE header + stream: true
|
|
546
|
+
4. Cache payment requirements for this model (1h TTL)
|
|
547
|
+
5. Stream tokens as they arrive
|
|
548
|
+
|
|
549
|
+
Subsequent calls (cache hit):
|
|
550
|
+
1. Pre-sign payment from cache — skip 402 round-trip
|
|
551
|
+
2. Send request with PAYMENT-SIGNATURE upfront
|
|
552
|
+
3. Stream tokens immediately (~200ms faster)
|
|
553
|
+
```
|
|
554
|
+
|
|
465
555
|
### List Available Models
|
|
466
556
|
|
|
467
557
|
```typescript
|
|
@@ -724,10 +814,12 @@ Full TypeScript support with exported types:
|
|
|
724
814
|
```typescript
|
|
725
815
|
import {
|
|
726
816
|
LLMClient,
|
|
817
|
+
OpenAI,
|
|
727
818
|
testnetClient,
|
|
728
819
|
type ChatMessage,
|
|
729
820
|
type ChatResponse,
|
|
730
821
|
type ChatOptions,
|
|
822
|
+
type ChatCompletionOptions,
|
|
731
823
|
type Model,
|
|
732
824
|
// Smart routing types
|
|
733
825
|
type SmartChatOptions,
|
|
@@ -738,6 +830,14 @@ import {
|
|
|
738
830
|
APIError,
|
|
739
831
|
PaymentError,
|
|
740
832
|
} from '@blockrun/llm';
|
|
833
|
+
|
|
834
|
+
// chatCompletionStream returns a standard fetch Response with SSE body
|
|
835
|
+
const streamResponse: Response = await client.chatCompletionStream(model, messages, options);
|
|
836
|
+
|
|
837
|
+
// OpenAI-compat stream returns AsyncIterable
|
|
838
|
+
const stream: AsyncIterable<OpenAIChatCompletionChunk> = await openaiClient.chat.completions.create({
|
|
839
|
+
model, messages, stream: true
|
|
840
|
+
});
|
|
741
841
|
```
|
|
742
842
|
|
|
743
843
|
## Agent Wallet Setup
|
|
@@ -862,6 +962,9 @@ When you make an API call, the SDK automatically handles x402 payment. It signs
|
|
|
862
962
|
### What is smart routing / ClawRouter?
|
|
863
963
|
ClawRouter is a built-in smart routing engine that analyzes your request across 14 dimensions and automatically picks the cheapest model capable of handling it. Routing happens locally in under 1ms. It can save up to 78% on LLM costs compared to using premium models for every request.
|
|
864
964
|
|
|
965
|
+
### Does it support streaming?
|
|
966
|
+
Yes — as of v1.6.1. Use `client.chatCompletionStream()` for native streaming or `stream: true` in the OpenAI-compatible client. Payment is handled automatically: the SDK signs USDC payment before streaming begins, and caches payment requirements per model so subsequent calls skip the 402 round-trip (~200ms faster).
|
|
967
|
+
|
|
865
968
|
### How much does it cost?
|
|
866
969
|
Pay only for what you use. Prices start at $0.0002 per request (GPT-5 Nano). There are no minimums, subscriptions, or monthly fees. $5 in USDC gets you thousands of requests.
|
|
867
970
|
|
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,7 @@ __export(index_exports, {
|
|
|
37
37
|
ImageClient: () => ImageClient,
|
|
38
38
|
KNOWN_PROVIDERS: () => KNOWN_PROVIDERS,
|
|
39
39
|
LLMClient: () => LLMClient,
|
|
40
|
+
MusicClient: () => MusicClient,
|
|
40
41
|
OpenAI: () => OpenAI,
|
|
41
42
|
PaymentError: () => PaymentError,
|
|
42
43
|
SOLANA_NETWORK: () => SOLANA_NETWORK,
|
|
@@ -1898,8 +1899,163 @@ var ImageClient = class {
|
|
|
1898
1899
|
}
|
|
1899
1900
|
};
|
|
1900
1901
|
|
|
1901
|
-
// src/
|
|
1902
|
+
// src/music.ts
|
|
1902
1903
|
var import_accounts4 = require("viem/accounts");
|
|
1904
|
+
var DEFAULT_API_URL3 = "https://blockrun.ai/api";
|
|
1905
|
+
var DEFAULT_MODEL2 = "minimax/music-2.5+";
|
|
1906
|
+
var DEFAULT_TIMEOUT3 = 21e4;
|
|
1907
|
+
var MusicClient = class {
|
|
1908
|
+
account;
|
|
1909
|
+
privateKey;
|
|
1910
|
+
apiUrl;
|
|
1911
|
+
timeout;
|
|
1912
|
+
sessionTotalUsd = 0;
|
|
1913
|
+
sessionCalls = 0;
|
|
1914
|
+
constructor(options = {}) {
|
|
1915
|
+
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
1916
|
+
const privateKey = options.privateKey || envKey;
|
|
1917
|
+
if (!privateKey) {
|
|
1918
|
+
throw new Error(
|
|
1919
|
+
"Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
|
|
1920
|
+
);
|
|
1921
|
+
}
|
|
1922
|
+
validatePrivateKey(privateKey);
|
|
1923
|
+
this.privateKey = privateKey;
|
|
1924
|
+
this.account = (0, import_accounts4.privateKeyToAccount)(privateKey);
|
|
1925
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL3;
|
|
1926
|
+
validateApiUrl(apiUrl);
|
|
1927
|
+
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
1928
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT3;
|
|
1929
|
+
}
|
|
1930
|
+
/**
|
|
1931
|
+
* Generate a music track from a text prompt.
|
|
1932
|
+
*
|
|
1933
|
+
* Takes 1-3 minutes. Returns a CDN URL valid for ~24h.
|
|
1934
|
+
*
|
|
1935
|
+
* @param prompt - Music style, mood, or description
|
|
1936
|
+
* @param options - Optional generation parameters
|
|
1937
|
+
* @returns MusicResponse with track URL and metadata
|
|
1938
|
+
*
|
|
1939
|
+
* @example
|
|
1940
|
+
* const result = await client.generate('chill lo-fi beats with piano');
|
|
1941
|
+
* console.log(result.data[0].url); // Download this URL — expires in 24h
|
|
1942
|
+
*
|
|
1943
|
+
* @example With lyrics
|
|
1944
|
+
* const result = await client.generate('upbeat pop song', {
|
|
1945
|
+
* instrumental: false,
|
|
1946
|
+
* lyrics: 'Hello world, this is my song...'
|
|
1947
|
+
* });
|
|
1948
|
+
*/
|
|
1949
|
+
async generate(prompt, options) {
|
|
1950
|
+
const instrumental = options?.instrumental ?? true;
|
|
1951
|
+
const lyrics = options?.lyrics?.trim();
|
|
1952
|
+
if (instrumental && lyrics) {
|
|
1953
|
+
throw new Error("Cannot specify lyrics when instrumental is true");
|
|
1954
|
+
}
|
|
1955
|
+
const body = {
|
|
1956
|
+
model: options?.model || DEFAULT_MODEL2,
|
|
1957
|
+
prompt,
|
|
1958
|
+
instrumental
|
|
1959
|
+
};
|
|
1960
|
+
if (lyrics) body.lyrics = lyrics;
|
|
1961
|
+
return this.requestWithPayment("/v1/audio/generations", body);
|
|
1962
|
+
}
|
|
1963
|
+
async requestWithPayment(endpoint, body) {
|
|
1964
|
+
const url = `${this.apiUrl}${endpoint}`;
|
|
1965
|
+
const response = await this.fetchWithTimeout(url, {
|
|
1966
|
+
method: "POST",
|
|
1967
|
+
headers: { "Content-Type": "application/json" },
|
|
1968
|
+
body: JSON.stringify(body)
|
|
1969
|
+
});
|
|
1970
|
+
if (response.status === 402) {
|
|
1971
|
+
return this.handlePaymentAndRetry(url, body, response);
|
|
1972
|
+
}
|
|
1973
|
+
if (!response.ok) {
|
|
1974
|
+
let errorBody;
|
|
1975
|
+
try {
|
|
1976
|
+
errorBody = await response.json();
|
|
1977
|
+
} catch {
|
|
1978
|
+
errorBody = { error: "Request failed" };
|
|
1979
|
+
}
|
|
1980
|
+
throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
|
|
1981
|
+
}
|
|
1982
|
+
return response.json();
|
|
1983
|
+
}
|
|
1984
|
+
async handlePaymentAndRetry(url, body, response) {
|
|
1985
|
+
let paymentHeader = response.headers.get("payment-required");
|
|
1986
|
+
if (!paymentHeader) {
|
|
1987
|
+
try {
|
|
1988
|
+
const respBody = await response.json();
|
|
1989
|
+
if (respBody.x402 || respBody.accepts) {
|
|
1990
|
+
paymentHeader = btoa(JSON.stringify(respBody));
|
|
1991
|
+
}
|
|
1992
|
+
} catch {
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
if (!paymentHeader) {
|
|
1996
|
+
throw new PaymentError("402 response but no payment requirements found");
|
|
1997
|
+
}
|
|
1998
|
+
const paymentRequired = parsePaymentRequired(paymentHeader);
|
|
1999
|
+
const details = extractPaymentDetails(paymentRequired);
|
|
2000
|
+
const paymentPayload = await createPaymentPayload(
|
|
2001
|
+
this.privateKey,
|
|
2002
|
+
this.account.address,
|
|
2003
|
+
details.recipient,
|
|
2004
|
+
details.amount,
|
|
2005
|
+
details.network || "eip155:8453",
|
|
2006
|
+
{
|
|
2007
|
+
resourceUrl: details.resource?.url || `${this.apiUrl}/v1/audio/generations`,
|
|
2008
|
+
resourceDescription: details.resource?.description || "BlockRun Music Generation",
|
|
2009
|
+
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
2010
|
+
extra: details.extra
|
|
2011
|
+
}
|
|
2012
|
+
);
|
|
2013
|
+
const retryResponse = await this.fetchWithTimeout(url, {
|
|
2014
|
+
method: "POST",
|
|
2015
|
+
headers: {
|
|
2016
|
+
"Content-Type": "application/json",
|
|
2017
|
+
"PAYMENT-SIGNATURE": paymentPayload
|
|
2018
|
+
},
|
|
2019
|
+
body: JSON.stringify(body)
|
|
2020
|
+
});
|
|
2021
|
+
if (retryResponse.status === 402) {
|
|
2022
|
+
throw new PaymentError("Payment was rejected. Check your wallet balance.");
|
|
2023
|
+
}
|
|
2024
|
+
if (!retryResponse.ok) {
|
|
2025
|
+
let errorBody;
|
|
2026
|
+
try {
|
|
2027
|
+
errorBody = await retryResponse.json();
|
|
2028
|
+
} catch {
|
|
2029
|
+
errorBody = { error: "Request failed" };
|
|
2030
|
+
}
|
|
2031
|
+
throw new APIError(`API error after payment: ${retryResponse.status}`, retryResponse.status, sanitizeErrorResponse(errorBody));
|
|
2032
|
+
}
|
|
2033
|
+
const data = await retryResponse.json();
|
|
2034
|
+
this.sessionCalls++;
|
|
2035
|
+
this.sessionTotalUsd += 0.1575;
|
|
2036
|
+
const txHash = retryResponse.headers.get("x-payment-receipt") || retryResponse.headers.get("X-Payment-Receipt");
|
|
2037
|
+
if (txHash) data.txHash = txHash;
|
|
2038
|
+
return data;
|
|
2039
|
+
}
|
|
2040
|
+
async fetchWithTimeout(url, options) {
|
|
2041
|
+
const controller = new AbortController();
|
|
2042
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
2043
|
+
try {
|
|
2044
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
2045
|
+
} finally {
|
|
2046
|
+
clearTimeout(timeoutId);
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
getWalletAddress() {
|
|
2050
|
+
return this.account.address;
|
|
2051
|
+
}
|
|
2052
|
+
getSpending() {
|
|
2053
|
+
return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
|
|
2054
|
+
}
|
|
2055
|
+
};
|
|
2056
|
+
|
|
2057
|
+
// src/wallet.ts
|
|
2058
|
+
var import_accounts5 = require("viem/accounts");
|
|
1903
2059
|
var fs = __toESM(require("fs"), 1);
|
|
1904
2060
|
var path = __toESM(require("path"), 1);
|
|
1905
2061
|
var os = __toESM(require("os"), 1);
|
|
@@ -1908,8 +2064,8 @@ var BASE_CHAIN_ID2 = "8453";
|
|
|
1908
2064
|
var WALLET_DIR = path.join(os.homedir(), ".blockrun");
|
|
1909
2065
|
var WALLET_FILE = path.join(WALLET_DIR, ".session");
|
|
1910
2066
|
function createWallet() {
|
|
1911
|
-
const privateKey = (0,
|
|
1912
|
-
const account = (0,
|
|
2067
|
+
const privateKey = (0, import_accounts5.generatePrivateKey)();
|
|
2068
|
+
const account = (0, import_accounts5.privateKeyToAccount)(privateKey);
|
|
1913
2069
|
return {
|
|
1914
2070
|
address: account.address,
|
|
1915
2071
|
privateKey
|
|
@@ -1965,12 +2121,12 @@ function loadWallet() {
|
|
|
1965
2121
|
function getOrCreateWallet() {
|
|
1966
2122
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
1967
2123
|
if (envKey) {
|
|
1968
|
-
const account = (0,
|
|
2124
|
+
const account = (0, import_accounts5.privateKeyToAccount)(envKey);
|
|
1969
2125
|
return { address: account.address, privateKey: envKey, isNew: false };
|
|
1970
2126
|
}
|
|
1971
2127
|
const fileKey = loadWallet();
|
|
1972
2128
|
if (fileKey) {
|
|
1973
|
-
const account = (0,
|
|
2129
|
+
const account = (0, import_accounts5.privateKeyToAccount)(fileKey);
|
|
1974
2130
|
return { address: account.address, privateKey: fileKey, isNew: false };
|
|
1975
2131
|
}
|
|
1976
2132
|
const { address, privateKey } = createWallet();
|
|
@@ -1980,11 +2136,11 @@ function getOrCreateWallet() {
|
|
|
1980
2136
|
function getWalletAddress() {
|
|
1981
2137
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
1982
2138
|
if (envKey) {
|
|
1983
|
-
return (0,
|
|
2139
|
+
return (0, import_accounts5.privateKeyToAccount)(envKey).address;
|
|
1984
2140
|
}
|
|
1985
2141
|
const fileKey = loadWallet();
|
|
1986
2142
|
if (fileKey) {
|
|
1987
|
-
return (0,
|
|
2143
|
+
return (0, import_accounts5.privateKeyToAccount)(fileKey).address;
|
|
1988
2144
|
}
|
|
1989
2145
|
return null;
|
|
1990
2146
|
}
|
|
@@ -2164,7 +2320,7 @@ async function getOrCreateSolanaWallet() {
|
|
|
2164
2320
|
// src/solana-client.ts
|
|
2165
2321
|
var SOLANA_API_URL = "https://sol.blockrun.ai/api";
|
|
2166
2322
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
2167
|
-
var
|
|
2323
|
+
var DEFAULT_TIMEOUT4 = 6e4;
|
|
2168
2324
|
var SDK_VERSION2 = "0.3.0";
|
|
2169
2325
|
var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
|
|
2170
2326
|
var SolanaLLMClient = class {
|
|
@@ -2189,7 +2345,7 @@ var SolanaLLMClient = class {
|
|
|
2189
2345
|
validateApiUrl(apiUrl);
|
|
2190
2346
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2191
2347
|
this.rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
|
|
2192
|
-
this.timeout = options.timeout ||
|
|
2348
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT4;
|
|
2193
2349
|
}
|
|
2194
2350
|
/** Get Solana wallet address (public key in base58). */
|
|
2195
2351
|
async getWalletAddress() {
|
|
@@ -3134,7 +3290,7 @@ var OpenAI = class {
|
|
|
3134
3290
|
};
|
|
3135
3291
|
|
|
3136
3292
|
// src/anthropic-compat.ts
|
|
3137
|
-
var
|
|
3293
|
+
var import_accounts6 = require("viem/accounts");
|
|
3138
3294
|
var AnthropicClient = class {
|
|
3139
3295
|
_client = null;
|
|
3140
3296
|
_clientPromise = null;
|
|
@@ -3147,7 +3303,7 @@ var AnthropicClient = class {
|
|
|
3147
3303
|
const key = options.privateKey ?? wallet.privateKey;
|
|
3148
3304
|
validatePrivateKey(key);
|
|
3149
3305
|
this._privateKey = key;
|
|
3150
|
-
this._account = (0,
|
|
3306
|
+
this._account = (0, import_accounts6.privateKeyToAccount)(this._privateKey);
|
|
3151
3307
|
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
3152
3308
|
validateApiUrl(apiUrl);
|
|
3153
3309
|
this._apiUrl = apiUrl.replace(/\/$/, "");
|
|
@@ -3250,6 +3406,7 @@ var AnthropicClient = class {
|
|
|
3250
3406
|
ImageClient,
|
|
3251
3407
|
KNOWN_PROVIDERS,
|
|
3252
3408
|
LLMClient,
|
|
3409
|
+
MusicClient,
|
|
3253
3410
|
OpenAI,
|
|
3254
3411
|
PaymentError,
|
|
3255
3412
|
SOLANA_NETWORK,
|
package/dist/index.d.cts
CHANGED
|
@@ -70,6 +70,10 @@ interface Model {
|
|
|
70
70
|
}
|
|
71
71
|
interface ImageData {
|
|
72
72
|
url: string;
|
|
73
|
+
/** Original upstream URL (e.g. imgen.x.ai). Omitted for data URIs. */
|
|
74
|
+
source_url?: string;
|
|
75
|
+
/** True when the gateway mirrored the image to its GCS bucket. Omitted for data URIs. */
|
|
76
|
+
backed_up?: boolean;
|
|
73
77
|
revised_prompt?: string;
|
|
74
78
|
b64_json?: string;
|
|
75
79
|
}
|
|
@@ -286,6 +290,91 @@ interface ImageEditOptions {
|
|
|
286
290
|
/** Number of images to generate (default: 1) */
|
|
287
291
|
n?: number;
|
|
288
292
|
}
|
|
293
|
+
interface AudioTrack {
|
|
294
|
+
url: string;
|
|
295
|
+
duration_seconds?: number;
|
|
296
|
+
lyrics?: string;
|
|
297
|
+
}
|
|
298
|
+
interface MusicResponse {
|
|
299
|
+
created: number;
|
|
300
|
+
model: string;
|
|
301
|
+
data: AudioTrack[];
|
|
302
|
+
txHash?: string;
|
|
303
|
+
}
|
|
304
|
+
interface AudioModel {
|
|
305
|
+
id: string;
|
|
306
|
+
name: string;
|
|
307
|
+
provider: string;
|
|
308
|
+
description: string;
|
|
309
|
+
pricePerTrack: number;
|
|
310
|
+
maxDurationSeconds: number;
|
|
311
|
+
supportsLyrics: boolean;
|
|
312
|
+
supportsInstrumental: boolean;
|
|
313
|
+
available: boolean;
|
|
314
|
+
type: "audio";
|
|
315
|
+
}
|
|
316
|
+
interface MusicClientOptions {
|
|
317
|
+
/** EVM wallet private key (hex string starting with 0x) */
|
|
318
|
+
privateKey?: `0x${string}` | string;
|
|
319
|
+
/** API endpoint URL (default: https://blockrun.ai/api) */
|
|
320
|
+
apiUrl?: string;
|
|
321
|
+
/** Request timeout in milliseconds (default: 210000 — music gen takes 1-3 min) */
|
|
322
|
+
timeout?: number;
|
|
323
|
+
}
|
|
324
|
+
interface MusicGenerateOptions {
|
|
325
|
+
/** Model ID (default: "minimax/music-2.5+") */
|
|
326
|
+
model?: "minimax/music-2.5+" | "minimax/music-2.5";
|
|
327
|
+
/** Generate without vocals (default: true) */
|
|
328
|
+
instrumental?: boolean;
|
|
329
|
+
/** Custom lyrics — cannot be used with instrumental: true */
|
|
330
|
+
lyrics?: string;
|
|
331
|
+
}
|
|
332
|
+
interface VideoClip {
|
|
333
|
+
/** Permanent blockrun-hosted URL (falls back to upstream if backup fails) */
|
|
334
|
+
url: string;
|
|
335
|
+
/** Original upstream URL (e.g. vidgen.x.ai) */
|
|
336
|
+
source_url?: string;
|
|
337
|
+
/** Duration of the generated video */
|
|
338
|
+
duration_seconds?: number;
|
|
339
|
+
/** Upstream provider's request id (xAI) */
|
|
340
|
+
request_id?: string;
|
|
341
|
+
/** True when the gateway mirrored the video to its GCS bucket */
|
|
342
|
+
backed_up?: boolean;
|
|
343
|
+
}
|
|
344
|
+
interface VideoResponse {
|
|
345
|
+
created: number;
|
|
346
|
+
model: string;
|
|
347
|
+
data: VideoClip[];
|
|
348
|
+
txHash?: string;
|
|
349
|
+
}
|
|
350
|
+
interface VideoModel {
|
|
351
|
+
id: string;
|
|
352
|
+
name: string;
|
|
353
|
+
provider: string;
|
|
354
|
+
description: string;
|
|
355
|
+
pricePerSecond: number;
|
|
356
|
+
defaultDurationSeconds: number;
|
|
357
|
+
maxDurationSeconds: number;
|
|
358
|
+
supportsImageInput: boolean;
|
|
359
|
+
available: boolean;
|
|
360
|
+
type: "video";
|
|
361
|
+
}
|
|
362
|
+
interface VideoClientOptions {
|
|
363
|
+
/** EVM wallet private key (hex string starting with 0x) */
|
|
364
|
+
privateKey?: `0x${string}` | string;
|
|
365
|
+
/** API endpoint URL (default: https://blockrun.ai/api) */
|
|
366
|
+
apiUrl?: string;
|
|
367
|
+
/** Request timeout in milliseconds (default: 300000 — video gen + polling up to 3 min) */
|
|
368
|
+
timeout?: number;
|
|
369
|
+
}
|
|
370
|
+
interface VideoGenerateOptions {
|
|
371
|
+
/** Model ID (default: "xai/grok-imagine-video") */
|
|
372
|
+
model?: "xai/grok-imagine-video" | string;
|
|
373
|
+
/** Optional seed image URL for image-to-video */
|
|
374
|
+
imageUrl?: string;
|
|
375
|
+
/** Duration to bill for (defaults to model's default duration) */
|
|
376
|
+
durationSeconds?: number;
|
|
377
|
+
}
|
|
289
378
|
interface SearchOptions {
|
|
290
379
|
/** Source types to search (e.g. ["web", "x", "news"]) */
|
|
291
380
|
sources?: string[];
|
|
@@ -967,8 +1056,8 @@ declare function testnetClient(options?: Omit<LLMClientOptions, 'apiUrl'>): LLMC
|
|
|
967
1056
|
/**
|
|
968
1057
|
* BlockRun Image Generation Client.
|
|
969
1058
|
*
|
|
970
|
-
* Generate images using Nano Banana (Google Gemini), DALL-E 3,
|
|
971
|
-
* with automatic x402 micropayments on Base chain.
|
|
1059
|
+
* Generate images using Nano Banana (Google Gemini), DALL-E 3, GPT Image,
|
|
1060
|
+
* or CogView-4 (Zhipu AI) with automatic x402 micropayments on Base chain.
|
|
972
1061
|
*/
|
|
973
1062
|
declare class ImageClient {
|
|
974
1063
|
private account;
|
|
@@ -1034,6 +1123,67 @@ declare class ImageClient {
|
|
|
1034
1123
|
getSpending(): Spending;
|
|
1035
1124
|
}
|
|
1036
1125
|
|
|
1126
|
+
/**
|
|
1127
|
+
* BlockRun Music Client - Generate music tracks via x402 micropayments.
|
|
1128
|
+
*
|
|
1129
|
+
* SECURITY NOTE - Private Key Handling:
|
|
1130
|
+
* Your private key NEVER leaves your machine. Here's what happens:
|
|
1131
|
+
* 1. Key stays local - only used to sign an EIP-712 typed data message
|
|
1132
|
+
* 2. Only the SIGNATURE is sent in the PAYMENT-SIGNATURE header
|
|
1133
|
+
* 3. BlockRun verifies the signature on-chain via Coinbase CDP facilitator
|
|
1134
|
+
*
|
|
1135
|
+
* Usage:
|
|
1136
|
+
* import { MusicClient } from '@blockrun/llm';
|
|
1137
|
+
*
|
|
1138
|
+
* const client = new MusicClient({ privateKey: '0x...' });
|
|
1139
|
+
* const result = await client.generate('upbeat synthwave with neon pads');
|
|
1140
|
+
* console.log(result.data[0].url); // CDN URL — download within 24h
|
|
1141
|
+
*/
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* BlockRun Music Generation Client.
|
|
1145
|
+
*
|
|
1146
|
+
* Generate full-length ~3 minute music tracks using MiniMax Music 2.5+
|
|
1147
|
+
* with automatic x402 micropayments on Base chain.
|
|
1148
|
+
*
|
|
1149
|
+
* Pricing: $0.1575/track
|
|
1150
|
+
* Note: Generated URLs expire in ~24h — download immediately if needed.
|
|
1151
|
+
*/
|
|
1152
|
+
declare class MusicClient {
|
|
1153
|
+
private account;
|
|
1154
|
+
private privateKey;
|
|
1155
|
+
private apiUrl;
|
|
1156
|
+
private timeout;
|
|
1157
|
+
private sessionTotalUsd;
|
|
1158
|
+
private sessionCalls;
|
|
1159
|
+
constructor(options?: MusicClientOptions);
|
|
1160
|
+
/**
|
|
1161
|
+
* Generate a music track from a text prompt.
|
|
1162
|
+
*
|
|
1163
|
+
* Takes 1-3 minutes. Returns a CDN URL valid for ~24h.
|
|
1164
|
+
*
|
|
1165
|
+
* @param prompt - Music style, mood, or description
|
|
1166
|
+
* @param options - Optional generation parameters
|
|
1167
|
+
* @returns MusicResponse with track URL and metadata
|
|
1168
|
+
*
|
|
1169
|
+
* @example
|
|
1170
|
+
* const result = await client.generate('chill lo-fi beats with piano');
|
|
1171
|
+
* console.log(result.data[0].url); // Download this URL — expires in 24h
|
|
1172
|
+
*
|
|
1173
|
+
* @example With lyrics
|
|
1174
|
+
* const result = await client.generate('upbeat pop song', {
|
|
1175
|
+
* instrumental: false,
|
|
1176
|
+
* lyrics: 'Hello world, this is my song...'
|
|
1177
|
+
* });
|
|
1178
|
+
*/
|
|
1179
|
+
generate(prompt: string, options?: MusicGenerateOptions): Promise<MusicResponse>;
|
|
1180
|
+
private requestWithPayment;
|
|
1181
|
+
private handlePaymentAndRetry;
|
|
1182
|
+
private fetchWithTimeout;
|
|
1183
|
+
getWalletAddress(): string;
|
|
1184
|
+
getSpending(): Spending;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1037
1187
|
/**
|
|
1038
1188
|
* x402 Payment Protocol v2 Implementation for BlockRun.
|
|
1039
1189
|
*
|
|
@@ -1664,4 +1814,4 @@ declare function validateTemperature(temperature?: number): void;
|
|
|
1664
1814
|
*/
|
|
1665
1815
|
declare function validateTopP(topP?: number): void;
|
|
1666
1816
|
|
|
1667
|
-
export { APIError, AnthropicClient, BASE_CHAIN_ID, type BlockRunAnthropicOptions, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatResponseWithCost, type ChatUsage, type CostEntry, type CostEstimate, type CreatePaymentOptions, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, type ImageGenerateOptions, type ImageModel, type ImageResponse, KNOWN_PROVIDERS, 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 SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type SpendingReport, 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, createPaymentPayload, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, extractPaymentDetails, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getCached, getCachedByRequest, getCostLogSummary, getCostSummary, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadSolanaWallet, loadWallet, logCost, parsePaymentRequired, saveSolanaWallet, saveToCache, saveWallet, scanSolanaWallets, scanWallets, setCache, setupAgentSolanaWallet, setupAgentWallet, solanaClient, solanaKeyToBytes, solanaPublicKey, status, testnetClient, validateMaxTokens, validateModel, validateTemperature, validateTopP };
|
|
1817
|
+
export { APIError, AnthropicClient, type AudioModel, type AudioTrack, BASE_CHAIN_ID, type BlockRunAnthropicOptions, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatResponseWithCost, type ChatUsage, type CostEntry, type CostEstimate, type CreatePaymentOptions, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, type ImageGenerateOptions, type ImageModel, type ImageResponse, KNOWN_PROVIDERS, LLMClient, type LLMClientOptions, type Model, MusicClient, type MusicClientOptions, type MusicGenerateOptions, type MusicResponse, 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 SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type SpendingReport, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, type VideoClientOptions, type VideoClip, type VideoGenerateOptions, type VideoModel, type VideoResponse, 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, createPaymentPayload, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, extractPaymentDetails, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getCached, getCachedByRequest, getCostLogSummary, getCostSummary, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadSolanaWallet, loadWallet, logCost, parsePaymentRequired, saveSolanaWallet, saveToCache, saveWallet, scanSolanaWallets, scanWallets, setCache, setupAgentSolanaWallet, setupAgentWallet, solanaClient, solanaKeyToBytes, solanaPublicKey, status, testnetClient, validateMaxTokens, validateModel, validateTemperature, validateTopP };
|
package/dist/index.d.ts
CHANGED
|
@@ -70,6 +70,10 @@ interface Model {
|
|
|
70
70
|
}
|
|
71
71
|
interface ImageData {
|
|
72
72
|
url: string;
|
|
73
|
+
/** Original upstream URL (e.g. imgen.x.ai). Omitted for data URIs. */
|
|
74
|
+
source_url?: string;
|
|
75
|
+
/** True when the gateway mirrored the image to its GCS bucket. Omitted for data URIs. */
|
|
76
|
+
backed_up?: boolean;
|
|
73
77
|
revised_prompt?: string;
|
|
74
78
|
b64_json?: string;
|
|
75
79
|
}
|
|
@@ -286,6 +290,91 @@ interface ImageEditOptions {
|
|
|
286
290
|
/** Number of images to generate (default: 1) */
|
|
287
291
|
n?: number;
|
|
288
292
|
}
|
|
293
|
+
interface AudioTrack {
|
|
294
|
+
url: string;
|
|
295
|
+
duration_seconds?: number;
|
|
296
|
+
lyrics?: string;
|
|
297
|
+
}
|
|
298
|
+
interface MusicResponse {
|
|
299
|
+
created: number;
|
|
300
|
+
model: string;
|
|
301
|
+
data: AudioTrack[];
|
|
302
|
+
txHash?: string;
|
|
303
|
+
}
|
|
304
|
+
interface AudioModel {
|
|
305
|
+
id: string;
|
|
306
|
+
name: string;
|
|
307
|
+
provider: string;
|
|
308
|
+
description: string;
|
|
309
|
+
pricePerTrack: number;
|
|
310
|
+
maxDurationSeconds: number;
|
|
311
|
+
supportsLyrics: boolean;
|
|
312
|
+
supportsInstrumental: boolean;
|
|
313
|
+
available: boolean;
|
|
314
|
+
type: "audio";
|
|
315
|
+
}
|
|
316
|
+
interface MusicClientOptions {
|
|
317
|
+
/** EVM wallet private key (hex string starting with 0x) */
|
|
318
|
+
privateKey?: `0x${string}` | string;
|
|
319
|
+
/** API endpoint URL (default: https://blockrun.ai/api) */
|
|
320
|
+
apiUrl?: string;
|
|
321
|
+
/** Request timeout in milliseconds (default: 210000 — music gen takes 1-3 min) */
|
|
322
|
+
timeout?: number;
|
|
323
|
+
}
|
|
324
|
+
interface MusicGenerateOptions {
|
|
325
|
+
/** Model ID (default: "minimax/music-2.5+") */
|
|
326
|
+
model?: "minimax/music-2.5+" | "minimax/music-2.5";
|
|
327
|
+
/** Generate without vocals (default: true) */
|
|
328
|
+
instrumental?: boolean;
|
|
329
|
+
/** Custom lyrics — cannot be used with instrumental: true */
|
|
330
|
+
lyrics?: string;
|
|
331
|
+
}
|
|
332
|
+
interface VideoClip {
|
|
333
|
+
/** Permanent blockrun-hosted URL (falls back to upstream if backup fails) */
|
|
334
|
+
url: string;
|
|
335
|
+
/** Original upstream URL (e.g. vidgen.x.ai) */
|
|
336
|
+
source_url?: string;
|
|
337
|
+
/** Duration of the generated video */
|
|
338
|
+
duration_seconds?: number;
|
|
339
|
+
/** Upstream provider's request id (xAI) */
|
|
340
|
+
request_id?: string;
|
|
341
|
+
/** True when the gateway mirrored the video to its GCS bucket */
|
|
342
|
+
backed_up?: boolean;
|
|
343
|
+
}
|
|
344
|
+
interface VideoResponse {
|
|
345
|
+
created: number;
|
|
346
|
+
model: string;
|
|
347
|
+
data: VideoClip[];
|
|
348
|
+
txHash?: string;
|
|
349
|
+
}
|
|
350
|
+
interface VideoModel {
|
|
351
|
+
id: string;
|
|
352
|
+
name: string;
|
|
353
|
+
provider: string;
|
|
354
|
+
description: string;
|
|
355
|
+
pricePerSecond: number;
|
|
356
|
+
defaultDurationSeconds: number;
|
|
357
|
+
maxDurationSeconds: number;
|
|
358
|
+
supportsImageInput: boolean;
|
|
359
|
+
available: boolean;
|
|
360
|
+
type: "video";
|
|
361
|
+
}
|
|
362
|
+
interface VideoClientOptions {
|
|
363
|
+
/** EVM wallet private key (hex string starting with 0x) */
|
|
364
|
+
privateKey?: `0x${string}` | string;
|
|
365
|
+
/** API endpoint URL (default: https://blockrun.ai/api) */
|
|
366
|
+
apiUrl?: string;
|
|
367
|
+
/** Request timeout in milliseconds (default: 300000 — video gen + polling up to 3 min) */
|
|
368
|
+
timeout?: number;
|
|
369
|
+
}
|
|
370
|
+
interface VideoGenerateOptions {
|
|
371
|
+
/** Model ID (default: "xai/grok-imagine-video") */
|
|
372
|
+
model?: "xai/grok-imagine-video" | string;
|
|
373
|
+
/** Optional seed image URL for image-to-video */
|
|
374
|
+
imageUrl?: string;
|
|
375
|
+
/** Duration to bill for (defaults to model's default duration) */
|
|
376
|
+
durationSeconds?: number;
|
|
377
|
+
}
|
|
289
378
|
interface SearchOptions {
|
|
290
379
|
/** Source types to search (e.g. ["web", "x", "news"]) */
|
|
291
380
|
sources?: string[];
|
|
@@ -967,8 +1056,8 @@ declare function testnetClient(options?: Omit<LLMClientOptions, 'apiUrl'>): LLMC
|
|
|
967
1056
|
/**
|
|
968
1057
|
* BlockRun Image Generation Client.
|
|
969
1058
|
*
|
|
970
|
-
* Generate images using Nano Banana (Google Gemini), DALL-E 3,
|
|
971
|
-
* with automatic x402 micropayments on Base chain.
|
|
1059
|
+
* Generate images using Nano Banana (Google Gemini), DALL-E 3, GPT Image,
|
|
1060
|
+
* or CogView-4 (Zhipu AI) with automatic x402 micropayments on Base chain.
|
|
972
1061
|
*/
|
|
973
1062
|
declare class ImageClient {
|
|
974
1063
|
private account;
|
|
@@ -1034,6 +1123,67 @@ declare class ImageClient {
|
|
|
1034
1123
|
getSpending(): Spending;
|
|
1035
1124
|
}
|
|
1036
1125
|
|
|
1126
|
+
/**
|
|
1127
|
+
* BlockRun Music Client - Generate music tracks via x402 micropayments.
|
|
1128
|
+
*
|
|
1129
|
+
* SECURITY NOTE - Private Key Handling:
|
|
1130
|
+
* Your private key NEVER leaves your machine. Here's what happens:
|
|
1131
|
+
* 1. Key stays local - only used to sign an EIP-712 typed data message
|
|
1132
|
+
* 2. Only the SIGNATURE is sent in the PAYMENT-SIGNATURE header
|
|
1133
|
+
* 3. BlockRun verifies the signature on-chain via Coinbase CDP facilitator
|
|
1134
|
+
*
|
|
1135
|
+
* Usage:
|
|
1136
|
+
* import { MusicClient } from '@blockrun/llm';
|
|
1137
|
+
*
|
|
1138
|
+
* const client = new MusicClient({ privateKey: '0x...' });
|
|
1139
|
+
* const result = await client.generate('upbeat synthwave with neon pads');
|
|
1140
|
+
* console.log(result.data[0].url); // CDN URL — download within 24h
|
|
1141
|
+
*/
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* BlockRun Music Generation Client.
|
|
1145
|
+
*
|
|
1146
|
+
* Generate full-length ~3 minute music tracks using MiniMax Music 2.5+
|
|
1147
|
+
* with automatic x402 micropayments on Base chain.
|
|
1148
|
+
*
|
|
1149
|
+
* Pricing: $0.1575/track
|
|
1150
|
+
* Note: Generated URLs expire in ~24h — download immediately if needed.
|
|
1151
|
+
*/
|
|
1152
|
+
declare class MusicClient {
|
|
1153
|
+
private account;
|
|
1154
|
+
private privateKey;
|
|
1155
|
+
private apiUrl;
|
|
1156
|
+
private timeout;
|
|
1157
|
+
private sessionTotalUsd;
|
|
1158
|
+
private sessionCalls;
|
|
1159
|
+
constructor(options?: MusicClientOptions);
|
|
1160
|
+
/**
|
|
1161
|
+
* Generate a music track from a text prompt.
|
|
1162
|
+
*
|
|
1163
|
+
* Takes 1-3 minutes. Returns a CDN URL valid for ~24h.
|
|
1164
|
+
*
|
|
1165
|
+
* @param prompt - Music style, mood, or description
|
|
1166
|
+
* @param options - Optional generation parameters
|
|
1167
|
+
* @returns MusicResponse with track URL and metadata
|
|
1168
|
+
*
|
|
1169
|
+
* @example
|
|
1170
|
+
* const result = await client.generate('chill lo-fi beats with piano');
|
|
1171
|
+
* console.log(result.data[0].url); // Download this URL — expires in 24h
|
|
1172
|
+
*
|
|
1173
|
+
* @example With lyrics
|
|
1174
|
+
* const result = await client.generate('upbeat pop song', {
|
|
1175
|
+
* instrumental: false,
|
|
1176
|
+
* lyrics: 'Hello world, this is my song...'
|
|
1177
|
+
* });
|
|
1178
|
+
*/
|
|
1179
|
+
generate(prompt: string, options?: MusicGenerateOptions): Promise<MusicResponse>;
|
|
1180
|
+
private requestWithPayment;
|
|
1181
|
+
private handlePaymentAndRetry;
|
|
1182
|
+
private fetchWithTimeout;
|
|
1183
|
+
getWalletAddress(): string;
|
|
1184
|
+
getSpending(): Spending;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1037
1187
|
/**
|
|
1038
1188
|
* x402 Payment Protocol v2 Implementation for BlockRun.
|
|
1039
1189
|
*
|
|
@@ -1664,4 +1814,4 @@ declare function validateTemperature(temperature?: number): void;
|
|
|
1664
1814
|
*/
|
|
1665
1815
|
declare function validateTopP(topP?: number): void;
|
|
1666
1816
|
|
|
1667
|
-
export { APIError, AnthropicClient, BASE_CHAIN_ID, type BlockRunAnthropicOptions, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatResponseWithCost, type ChatUsage, type CostEntry, type CostEstimate, type CreatePaymentOptions, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, type ImageGenerateOptions, type ImageModel, type ImageResponse, KNOWN_PROVIDERS, 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 SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type SpendingReport, 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, createPaymentPayload, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, extractPaymentDetails, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getCached, getCachedByRequest, getCostLogSummary, getCostSummary, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadSolanaWallet, loadWallet, logCost, parsePaymentRequired, saveSolanaWallet, saveToCache, saveWallet, scanSolanaWallets, scanWallets, setCache, setupAgentSolanaWallet, setupAgentWallet, solanaClient, solanaKeyToBytes, solanaPublicKey, status, testnetClient, validateMaxTokens, validateModel, validateTemperature, validateTopP };
|
|
1817
|
+
export { APIError, AnthropicClient, type AudioModel, type AudioTrack, BASE_CHAIN_ID, type BlockRunAnthropicOptions, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatResponseWithCost, type ChatUsage, type CostEntry, type CostEstimate, type CreatePaymentOptions, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, type ImageGenerateOptions, type ImageModel, type ImageResponse, KNOWN_PROVIDERS, LLMClient, type LLMClientOptions, type Model, MusicClient, type MusicClientOptions, type MusicGenerateOptions, type MusicResponse, 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 SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type SpendingReport, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, type VideoClientOptions, type VideoClip, type VideoGenerateOptions, type VideoModel, type VideoResponse, 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, createPaymentPayload, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, extractPaymentDetails, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getCached, getCachedByRequest, getCostLogSummary, getCostSummary, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadSolanaWallet, loadWallet, logCost, parsePaymentRequired, saveSolanaWallet, saveToCache, saveWallet, scanSolanaWallets, scanWallets, setCache, setupAgentSolanaWallet, setupAgentWallet, solanaClient, solanaKeyToBytes, solanaPublicKey, status, testnetClient, validateMaxTokens, validateModel, validateTemperature, validateTopP };
|
package/dist/index.js
CHANGED
|
@@ -1813,8 +1813,163 @@ var ImageClient = class {
|
|
|
1813
1813
|
}
|
|
1814
1814
|
};
|
|
1815
1815
|
|
|
1816
|
+
// src/music.ts
|
|
1817
|
+
import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
|
|
1818
|
+
var DEFAULT_API_URL3 = "https://blockrun.ai/api";
|
|
1819
|
+
var DEFAULT_MODEL2 = "minimax/music-2.5+";
|
|
1820
|
+
var DEFAULT_TIMEOUT3 = 21e4;
|
|
1821
|
+
var MusicClient = class {
|
|
1822
|
+
account;
|
|
1823
|
+
privateKey;
|
|
1824
|
+
apiUrl;
|
|
1825
|
+
timeout;
|
|
1826
|
+
sessionTotalUsd = 0;
|
|
1827
|
+
sessionCalls = 0;
|
|
1828
|
+
constructor(options = {}) {
|
|
1829
|
+
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
1830
|
+
const privateKey = options.privateKey || envKey;
|
|
1831
|
+
if (!privateKey) {
|
|
1832
|
+
throw new Error(
|
|
1833
|
+
"Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
|
|
1834
|
+
);
|
|
1835
|
+
}
|
|
1836
|
+
validatePrivateKey(privateKey);
|
|
1837
|
+
this.privateKey = privateKey;
|
|
1838
|
+
this.account = privateKeyToAccount3(privateKey);
|
|
1839
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL3;
|
|
1840
|
+
validateApiUrl(apiUrl);
|
|
1841
|
+
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
1842
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT3;
|
|
1843
|
+
}
|
|
1844
|
+
/**
|
|
1845
|
+
* Generate a music track from a text prompt.
|
|
1846
|
+
*
|
|
1847
|
+
* Takes 1-3 minutes. Returns a CDN URL valid for ~24h.
|
|
1848
|
+
*
|
|
1849
|
+
* @param prompt - Music style, mood, or description
|
|
1850
|
+
* @param options - Optional generation parameters
|
|
1851
|
+
* @returns MusicResponse with track URL and metadata
|
|
1852
|
+
*
|
|
1853
|
+
* @example
|
|
1854
|
+
* const result = await client.generate('chill lo-fi beats with piano');
|
|
1855
|
+
* console.log(result.data[0].url); // Download this URL — expires in 24h
|
|
1856
|
+
*
|
|
1857
|
+
* @example With lyrics
|
|
1858
|
+
* const result = await client.generate('upbeat pop song', {
|
|
1859
|
+
* instrumental: false,
|
|
1860
|
+
* lyrics: 'Hello world, this is my song...'
|
|
1861
|
+
* });
|
|
1862
|
+
*/
|
|
1863
|
+
async generate(prompt, options) {
|
|
1864
|
+
const instrumental = options?.instrumental ?? true;
|
|
1865
|
+
const lyrics = options?.lyrics?.trim();
|
|
1866
|
+
if (instrumental && lyrics) {
|
|
1867
|
+
throw new Error("Cannot specify lyrics when instrumental is true");
|
|
1868
|
+
}
|
|
1869
|
+
const body = {
|
|
1870
|
+
model: options?.model || DEFAULT_MODEL2,
|
|
1871
|
+
prompt,
|
|
1872
|
+
instrumental
|
|
1873
|
+
};
|
|
1874
|
+
if (lyrics) body.lyrics = lyrics;
|
|
1875
|
+
return this.requestWithPayment("/v1/audio/generations", body);
|
|
1876
|
+
}
|
|
1877
|
+
async requestWithPayment(endpoint, body) {
|
|
1878
|
+
const url = `${this.apiUrl}${endpoint}`;
|
|
1879
|
+
const response = await this.fetchWithTimeout(url, {
|
|
1880
|
+
method: "POST",
|
|
1881
|
+
headers: { "Content-Type": "application/json" },
|
|
1882
|
+
body: JSON.stringify(body)
|
|
1883
|
+
});
|
|
1884
|
+
if (response.status === 402) {
|
|
1885
|
+
return this.handlePaymentAndRetry(url, body, response);
|
|
1886
|
+
}
|
|
1887
|
+
if (!response.ok) {
|
|
1888
|
+
let errorBody;
|
|
1889
|
+
try {
|
|
1890
|
+
errorBody = await response.json();
|
|
1891
|
+
} catch {
|
|
1892
|
+
errorBody = { error: "Request failed" };
|
|
1893
|
+
}
|
|
1894
|
+
throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
|
|
1895
|
+
}
|
|
1896
|
+
return response.json();
|
|
1897
|
+
}
|
|
1898
|
+
async handlePaymentAndRetry(url, body, response) {
|
|
1899
|
+
let paymentHeader = response.headers.get("payment-required");
|
|
1900
|
+
if (!paymentHeader) {
|
|
1901
|
+
try {
|
|
1902
|
+
const respBody = await response.json();
|
|
1903
|
+
if (respBody.x402 || respBody.accepts) {
|
|
1904
|
+
paymentHeader = btoa(JSON.stringify(respBody));
|
|
1905
|
+
}
|
|
1906
|
+
} catch {
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
if (!paymentHeader) {
|
|
1910
|
+
throw new PaymentError("402 response but no payment requirements found");
|
|
1911
|
+
}
|
|
1912
|
+
const paymentRequired = parsePaymentRequired(paymentHeader);
|
|
1913
|
+
const details = extractPaymentDetails(paymentRequired);
|
|
1914
|
+
const paymentPayload = await createPaymentPayload(
|
|
1915
|
+
this.privateKey,
|
|
1916
|
+
this.account.address,
|
|
1917
|
+
details.recipient,
|
|
1918
|
+
details.amount,
|
|
1919
|
+
details.network || "eip155:8453",
|
|
1920
|
+
{
|
|
1921
|
+
resourceUrl: details.resource?.url || `${this.apiUrl}/v1/audio/generations`,
|
|
1922
|
+
resourceDescription: details.resource?.description || "BlockRun Music Generation",
|
|
1923
|
+
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
1924
|
+
extra: details.extra
|
|
1925
|
+
}
|
|
1926
|
+
);
|
|
1927
|
+
const retryResponse = await this.fetchWithTimeout(url, {
|
|
1928
|
+
method: "POST",
|
|
1929
|
+
headers: {
|
|
1930
|
+
"Content-Type": "application/json",
|
|
1931
|
+
"PAYMENT-SIGNATURE": paymentPayload
|
|
1932
|
+
},
|
|
1933
|
+
body: JSON.stringify(body)
|
|
1934
|
+
});
|
|
1935
|
+
if (retryResponse.status === 402) {
|
|
1936
|
+
throw new PaymentError("Payment was rejected. Check your wallet balance.");
|
|
1937
|
+
}
|
|
1938
|
+
if (!retryResponse.ok) {
|
|
1939
|
+
let errorBody;
|
|
1940
|
+
try {
|
|
1941
|
+
errorBody = await retryResponse.json();
|
|
1942
|
+
} catch {
|
|
1943
|
+
errorBody = { error: "Request failed" };
|
|
1944
|
+
}
|
|
1945
|
+
throw new APIError(`API error after payment: ${retryResponse.status}`, retryResponse.status, sanitizeErrorResponse(errorBody));
|
|
1946
|
+
}
|
|
1947
|
+
const data = await retryResponse.json();
|
|
1948
|
+
this.sessionCalls++;
|
|
1949
|
+
this.sessionTotalUsd += 0.1575;
|
|
1950
|
+
const txHash = retryResponse.headers.get("x-payment-receipt") || retryResponse.headers.get("X-Payment-Receipt");
|
|
1951
|
+
if (txHash) data.txHash = txHash;
|
|
1952
|
+
return data;
|
|
1953
|
+
}
|
|
1954
|
+
async fetchWithTimeout(url, options) {
|
|
1955
|
+
const controller = new AbortController();
|
|
1956
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
1957
|
+
try {
|
|
1958
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
1959
|
+
} finally {
|
|
1960
|
+
clearTimeout(timeoutId);
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
getWalletAddress() {
|
|
1964
|
+
return this.account.address;
|
|
1965
|
+
}
|
|
1966
|
+
getSpending() {
|
|
1967
|
+
return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
|
|
1968
|
+
}
|
|
1969
|
+
};
|
|
1970
|
+
|
|
1816
1971
|
// src/wallet.ts
|
|
1817
|
-
import { privateKeyToAccount as
|
|
1972
|
+
import { privateKeyToAccount as privateKeyToAccount4, generatePrivateKey } from "viem/accounts";
|
|
1818
1973
|
import * as fs from "fs";
|
|
1819
1974
|
import * as path from "path";
|
|
1820
1975
|
import * as os from "os";
|
|
@@ -1824,7 +1979,7 @@ var WALLET_DIR = path.join(os.homedir(), ".blockrun");
|
|
|
1824
1979
|
var WALLET_FILE = path.join(WALLET_DIR, ".session");
|
|
1825
1980
|
function createWallet() {
|
|
1826
1981
|
const privateKey = generatePrivateKey();
|
|
1827
|
-
const account =
|
|
1982
|
+
const account = privateKeyToAccount4(privateKey);
|
|
1828
1983
|
return {
|
|
1829
1984
|
address: account.address,
|
|
1830
1985
|
privateKey
|
|
@@ -1880,12 +2035,12 @@ function loadWallet() {
|
|
|
1880
2035
|
function getOrCreateWallet() {
|
|
1881
2036
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
1882
2037
|
if (envKey) {
|
|
1883
|
-
const account =
|
|
2038
|
+
const account = privateKeyToAccount4(envKey);
|
|
1884
2039
|
return { address: account.address, privateKey: envKey, isNew: false };
|
|
1885
2040
|
}
|
|
1886
2041
|
const fileKey = loadWallet();
|
|
1887
2042
|
if (fileKey) {
|
|
1888
|
-
const account =
|
|
2043
|
+
const account = privateKeyToAccount4(fileKey);
|
|
1889
2044
|
return { address: account.address, privateKey: fileKey, isNew: false };
|
|
1890
2045
|
}
|
|
1891
2046
|
const { address, privateKey } = createWallet();
|
|
@@ -1895,11 +2050,11 @@ function getOrCreateWallet() {
|
|
|
1895
2050
|
function getWalletAddress() {
|
|
1896
2051
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
1897
2052
|
if (envKey) {
|
|
1898
|
-
return
|
|
2053
|
+
return privateKeyToAccount4(envKey).address;
|
|
1899
2054
|
}
|
|
1900
2055
|
const fileKey = loadWallet();
|
|
1901
2056
|
if (fileKey) {
|
|
1902
|
-
return
|
|
2057
|
+
return privateKeyToAccount4(fileKey).address;
|
|
1903
2058
|
}
|
|
1904
2059
|
return null;
|
|
1905
2060
|
}
|
|
@@ -2079,7 +2234,7 @@ async function getOrCreateSolanaWallet() {
|
|
|
2079
2234
|
// src/solana-client.ts
|
|
2080
2235
|
var SOLANA_API_URL = "https://sol.blockrun.ai/api";
|
|
2081
2236
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
2082
|
-
var
|
|
2237
|
+
var DEFAULT_TIMEOUT4 = 6e4;
|
|
2083
2238
|
var SDK_VERSION2 = "0.3.0";
|
|
2084
2239
|
var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
|
|
2085
2240
|
var SolanaLLMClient = class {
|
|
@@ -2104,7 +2259,7 @@ var SolanaLLMClient = class {
|
|
|
2104
2259
|
validateApiUrl(apiUrl);
|
|
2105
2260
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2106
2261
|
this.rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
|
|
2107
|
-
this.timeout = options.timeout ||
|
|
2262
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT4;
|
|
2108
2263
|
}
|
|
2109
2264
|
/** Get Solana wallet address (public key in base58). */
|
|
2110
2265
|
async getWalletAddress() {
|
|
@@ -3049,7 +3204,7 @@ var OpenAI = class {
|
|
|
3049
3204
|
};
|
|
3050
3205
|
|
|
3051
3206
|
// src/anthropic-compat.ts
|
|
3052
|
-
import { privateKeyToAccount as
|
|
3207
|
+
import { privateKeyToAccount as privateKeyToAccount5 } from "viem/accounts";
|
|
3053
3208
|
var AnthropicClient = class {
|
|
3054
3209
|
_client = null;
|
|
3055
3210
|
_clientPromise = null;
|
|
@@ -3062,7 +3217,7 @@ var AnthropicClient = class {
|
|
|
3062
3217
|
const key = options.privateKey ?? wallet.privateKey;
|
|
3063
3218
|
validatePrivateKey(key);
|
|
3064
3219
|
this._privateKey = key;
|
|
3065
|
-
this._account =
|
|
3220
|
+
this._account = privateKeyToAccount5(this._privateKey);
|
|
3066
3221
|
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
3067
3222
|
validateApiUrl(apiUrl);
|
|
3068
3223
|
this._apiUrl = apiUrl.replace(/\/$/, "");
|
|
@@ -3164,6 +3319,7 @@ export {
|
|
|
3164
3319
|
ImageClient,
|
|
3165
3320
|
KNOWN_PROVIDERS,
|
|
3166
3321
|
LLMClient,
|
|
3322
|
+
MusicClient,
|
|
3167
3323
|
OpenAI,
|
|
3168
3324
|
PaymentError,
|
|
3169
3325
|
SOLANA_NETWORK,
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/llm",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "BlockRun
|
|
5
|
+
"description": "BlockRun SDK - Pay-per-request AI (LLM, Image, Video, Music) via x402 on Base and Solana",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|