@blockrun/llm 2.1.1 → 2.2.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 +29 -0
- package/dist/index.cjs +228 -25
- package/dist/index.d.cts +146 -1
- package/dist/index.d.ts +146 -1
- package/dist/index.js +226 -24
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -383,6 +383,35 @@ const r2 = await client.generate('the subject turns and smiles', {
|
|
|
383
383
|
});
|
|
384
384
|
```
|
|
385
385
|
|
|
386
|
+
### Voice Calls
|
|
387
|
+
|
|
388
|
+
`VoiceClient` wraps `POST /v1/voice/call` (paid, $0.54/call) and
|
|
389
|
+
`GET /v1/voice/call/{callId}` (free polling) — AI-powered outbound phone
|
|
390
|
+
calls powered by Bland.ai. The agent dials the recipient and runs a real-time
|
|
391
|
+
conversation based on your `task` instructions. US + Canada destinations.
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
import { VoiceClient } from '@blockrun/llm';
|
|
395
|
+
|
|
396
|
+
const client = new VoiceClient();
|
|
397
|
+
|
|
398
|
+
// Initiate (paid $0.54)
|
|
399
|
+
const result = await client.call({
|
|
400
|
+
to: '+14155552671',
|
|
401
|
+
task: 'You are a friendly assistant calling to confirm a 3pm dentist appointment.',
|
|
402
|
+
voice: 'maya', // 'nat' | 'josh' | 'maya' | 'june' | 'paige' | 'derek' | 'florian'
|
|
403
|
+
max_duration: 5, // minutes (1–30)
|
|
404
|
+
});
|
|
405
|
+
console.log(result.call_id);
|
|
406
|
+
|
|
407
|
+
// Poll for transcript + recording (free)
|
|
408
|
+
const status = await client.getStatus(result.call_id);
|
|
409
|
+
console.log(status.status, status.recording_url);
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Bring your own caller-ID: pass `from: '+14155552671'` (must be a BlockRun
|
|
413
|
+
phone number you own; buy via `/v1/phone/numbers/buy`).
|
|
414
|
+
|
|
386
415
|
### Standalone Search
|
|
387
416
|
|
|
388
417
|
`SearchClient` wraps `POST /v1/search` — standalone Grok Live Search.
|
package/dist/index.cjs
CHANGED
|
@@ -49,6 +49,7 @@ __export(index_exports, {
|
|
|
49
49
|
USDC_BASE_CONTRACT: () => USDC_BASE_CONTRACT,
|
|
50
50
|
USDC_SOLANA: () => USDC_SOLANA,
|
|
51
51
|
VideoClient: () => VideoClient,
|
|
52
|
+
VoiceClient: () => VoiceClient,
|
|
52
53
|
WALLET_DIR_PATH: () => WALLET_DIR_PATH,
|
|
53
54
|
WALLET_FILE_PATH: () => WALLET_FILE_PATH,
|
|
54
55
|
XClient: () => XClient,
|
|
@@ -2557,15 +2558,19 @@ var VideoClient = class {
|
|
|
2557
2558
|
}
|
|
2558
2559
|
};
|
|
2559
2560
|
|
|
2560
|
-
// src/
|
|
2561
|
+
// src/voice.ts
|
|
2561
2562
|
var import_accounts6 = require("viem/accounts");
|
|
2562
2563
|
var DEFAULT_API_URL5 = "https://blockrun.ai/api";
|
|
2563
2564
|
var DEFAULT_TIMEOUT5 = 6e4;
|
|
2564
|
-
var
|
|
2565
|
+
var CALL_PRICE_USD = 0.54;
|
|
2566
|
+
var VALID_MODELS = /* @__PURE__ */ new Set(["base", "enhanced", "turbo"]);
|
|
2567
|
+
var VoiceClient = class {
|
|
2565
2568
|
account;
|
|
2566
2569
|
privateKey;
|
|
2567
2570
|
apiUrl;
|
|
2568
2571
|
timeout;
|
|
2572
|
+
sessionTotalUsd = 0;
|
|
2573
|
+
sessionCalls = 0;
|
|
2569
2574
|
constructor(options = {}) {
|
|
2570
2575
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
2571
2576
|
const privateKey = options.privateKey || envKey;
|
|
@@ -2582,6 +2587,203 @@ var SearchClient = class {
|
|
|
2582
2587
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2583
2588
|
this.timeout = options.timeout || DEFAULT_TIMEOUT5;
|
|
2584
2589
|
}
|
|
2590
|
+
/**
|
|
2591
|
+
* Initiate an AI-powered outbound phone call.
|
|
2592
|
+
*
|
|
2593
|
+
* Pricing: $0.54 per call. Returns immediately once the call is queued —
|
|
2594
|
+
* poll getStatus() for transcript and recording.
|
|
2595
|
+
*
|
|
2596
|
+
* @example
|
|
2597
|
+
* const r = await client.call({
|
|
2598
|
+
* to: '+14155552671',
|
|
2599
|
+
* task: 'Confirm the user wants to reschedule to Tuesday 2pm.',
|
|
2600
|
+
* voice: 'maya',
|
|
2601
|
+
* max_duration: 3,
|
|
2602
|
+
* });
|
|
2603
|
+
*/
|
|
2604
|
+
async call(options) {
|
|
2605
|
+
if (!options.to || !options.to.trim()) {
|
|
2606
|
+
throw new Error("'to' phone number is required (E.164 format)");
|
|
2607
|
+
}
|
|
2608
|
+
const task = options.task?.trim() ?? "";
|
|
2609
|
+
if (task.length < 10) {
|
|
2610
|
+
throw new Error("'task' must be at least 10 characters");
|
|
2611
|
+
}
|
|
2612
|
+
if (task.length > 4e3) {
|
|
2613
|
+
throw new Error("'task' must be at most 4000 characters");
|
|
2614
|
+
}
|
|
2615
|
+
const maxDuration = options.max_duration ?? 5;
|
|
2616
|
+
if (maxDuration < 1 || maxDuration > 30) {
|
|
2617
|
+
throw new Error("max_duration must be between 1 and 30 minutes");
|
|
2618
|
+
}
|
|
2619
|
+
if (options.model && !VALID_MODELS.has(options.model)) {
|
|
2620
|
+
throw new Error("model must be 'base' | 'enhanced' | 'turbo'");
|
|
2621
|
+
}
|
|
2622
|
+
if (options.interruption_threshold !== void 0 && (options.interruption_threshold < 50 || options.interruption_threshold > 500)) {
|
|
2623
|
+
throw new Error("interruption_threshold must be between 50 and 500");
|
|
2624
|
+
}
|
|
2625
|
+
const body = {
|
|
2626
|
+
to: options.to.trim(),
|
|
2627
|
+
task,
|
|
2628
|
+
max_duration: maxDuration,
|
|
2629
|
+
language: options.language ?? "en-US"
|
|
2630
|
+
};
|
|
2631
|
+
if (options.from) body.from = options.from.trim();
|
|
2632
|
+
if (options.voice) body.voice = options.voice;
|
|
2633
|
+
if (options.first_sentence) body.first_sentence = options.first_sentence.trim();
|
|
2634
|
+
if (options.wait_for_greeting !== void 0) body.wait_for_greeting = options.wait_for_greeting;
|
|
2635
|
+
if (options.interruption_threshold !== void 0) body.interruption_threshold = options.interruption_threshold;
|
|
2636
|
+
if (options.model) body.model = options.model;
|
|
2637
|
+
return this.requestWithPayment("/v1/voice/call", body);
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Poll the status of an in-progress or completed call. Free — no payment.
|
|
2641
|
+
*
|
|
2642
|
+
* Returns Bland.ai's full call record: status, transcript, recording URL, etc.
|
|
2643
|
+
* Most fields populate only once the call ends.
|
|
2644
|
+
*/
|
|
2645
|
+
async getStatus(callId) {
|
|
2646
|
+
if (!callId || !callId.trim()) {
|
|
2647
|
+
throw new Error("callId is required");
|
|
2648
|
+
}
|
|
2649
|
+
const url = `${this.apiUrl}/v1/voice/call/${encodeURIComponent(callId.trim())}`;
|
|
2650
|
+
const response = await this.fetchWithTimeout(url, {
|
|
2651
|
+
method: "GET",
|
|
2652
|
+
headers: { Accept: "application/json" }
|
|
2653
|
+
});
|
|
2654
|
+
if (response.status === 404) {
|
|
2655
|
+
throw new APIError(`Call not found: ${callId}`, 404, { call_id: callId });
|
|
2656
|
+
}
|
|
2657
|
+
if (!response.ok) {
|
|
2658
|
+
let errorBody;
|
|
2659
|
+
try {
|
|
2660
|
+
errorBody = await response.json();
|
|
2661
|
+
} catch {
|
|
2662
|
+
errorBody = { error: "Request failed" };
|
|
2663
|
+
}
|
|
2664
|
+
throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
|
|
2665
|
+
}
|
|
2666
|
+
return response.json();
|
|
2667
|
+
}
|
|
2668
|
+
async requestWithPayment(endpoint, body) {
|
|
2669
|
+
const url = `${this.apiUrl}${endpoint}`;
|
|
2670
|
+
const response = await this.fetchWithTimeout(url, {
|
|
2671
|
+
method: "POST",
|
|
2672
|
+
headers: { "Content-Type": "application/json" },
|
|
2673
|
+
body: JSON.stringify(body)
|
|
2674
|
+
});
|
|
2675
|
+
if (response.status === 402) {
|
|
2676
|
+
return this.handlePaymentAndRetry(url, body, response);
|
|
2677
|
+
}
|
|
2678
|
+
if (!response.ok) {
|
|
2679
|
+
let errorBody;
|
|
2680
|
+
try {
|
|
2681
|
+
errorBody = await response.json();
|
|
2682
|
+
} catch {
|
|
2683
|
+
errorBody = { error: "Request failed" };
|
|
2684
|
+
}
|
|
2685
|
+
throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
|
|
2686
|
+
}
|
|
2687
|
+
return response.json();
|
|
2688
|
+
}
|
|
2689
|
+
async handlePaymentAndRetry(url, body, response) {
|
|
2690
|
+
let paymentHeader = response.headers.get("payment-required");
|
|
2691
|
+
if (!paymentHeader) {
|
|
2692
|
+
try {
|
|
2693
|
+
const respBody = await response.json();
|
|
2694
|
+
if (respBody.x402 || respBody.accepts) {
|
|
2695
|
+
paymentHeader = btoa(JSON.stringify(respBody));
|
|
2696
|
+
}
|
|
2697
|
+
} catch {
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
if (!paymentHeader) {
|
|
2701
|
+
throw new PaymentError("402 response but no payment requirements found");
|
|
2702
|
+
}
|
|
2703
|
+
const paymentRequired = parsePaymentRequired(paymentHeader);
|
|
2704
|
+
const details = extractPaymentDetails(paymentRequired);
|
|
2705
|
+
const paymentPayload = await createPaymentPayload(
|
|
2706
|
+
this.privateKey,
|
|
2707
|
+
this.account.address,
|
|
2708
|
+
details.recipient,
|
|
2709
|
+
details.amount,
|
|
2710
|
+
details.network || "eip155:8453",
|
|
2711
|
+
{
|
|
2712
|
+
resourceUrl: details.resource?.url || `${this.apiUrl}/v1/voice/call`,
|
|
2713
|
+
resourceDescription: details.resource?.description || "BlockRun Voice Call",
|
|
2714
|
+
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
2715
|
+
extra: details.extra
|
|
2716
|
+
}
|
|
2717
|
+
);
|
|
2718
|
+
const retryResponse = await this.fetchWithTimeout(url, {
|
|
2719
|
+
method: "POST",
|
|
2720
|
+
headers: {
|
|
2721
|
+
"Content-Type": "application/json",
|
|
2722
|
+
"PAYMENT-SIGNATURE": paymentPayload
|
|
2723
|
+
},
|
|
2724
|
+
body: JSON.stringify(body)
|
|
2725
|
+
});
|
|
2726
|
+
if (retryResponse.status === 402) {
|
|
2727
|
+
throw new PaymentError("Payment was rejected. Check your wallet balance.");
|
|
2728
|
+
}
|
|
2729
|
+
if (!retryResponse.ok) {
|
|
2730
|
+
let errorBody;
|
|
2731
|
+
try {
|
|
2732
|
+
errorBody = await retryResponse.json();
|
|
2733
|
+
} catch {
|
|
2734
|
+
errorBody = { error: "Request failed" };
|
|
2735
|
+
}
|
|
2736
|
+
throw new APIError(`API error after payment: ${retryResponse.status}`, retryResponse.status, sanitizeErrorResponse(errorBody));
|
|
2737
|
+
}
|
|
2738
|
+
const data = await retryResponse.json();
|
|
2739
|
+
this.sessionCalls++;
|
|
2740
|
+
this.sessionTotalUsd += CALL_PRICE_USD;
|
|
2741
|
+
const txHash = retryResponse.headers.get("x-payment-receipt") || retryResponse.headers.get("X-Payment-Receipt");
|
|
2742
|
+
if (txHash) data.txHash = txHash;
|
|
2743
|
+
return data;
|
|
2744
|
+
}
|
|
2745
|
+
async fetchWithTimeout(url, options) {
|
|
2746
|
+
const controller = new AbortController();
|
|
2747
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
2748
|
+
try {
|
|
2749
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
2750
|
+
} finally {
|
|
2751
|
+
clearTimeout(timeoutId);
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
getWalletAddress() {
|
|
2755
|
+
return this.account.address;
|
|
2756
|
+
}
|
|
2757
|
+
getSpending() {
|
|
2758
|
+
return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
|
|
2759
|
+
}
|
|
2760
|
+
};
|
|
2761
|
+
|
|
2762
|
+
// src/search.ts
|
|
2763
|
+
var import_accounts7 = require("viem/accounts");
|
|
2764
|
+
var DEFAULT_API_URL6 = "https://blockrun.ai/api";
|
|
2765
|
+
var DEFAULT_TIMEOUT6 = 6e4;
|
|
2766
|
+
var SearchClient = class {
|
|
2767
|
+
account;
|
|
2768
|
+
privateKey;
|
|
2769
|
+
apiUrl;
|
|
2770
|
+
timeout;
|
|
2771
|
+
constructor(options = {}) {
|
|
2772
|
+
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
2773
|
+
const privateKey = options.privateKey || envKey;
|
|
2774
|
+
if (!privateKey) {
|
|
2775
|
+
throw new Error(
|
|
2776
|
+
"Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
|
|
2777
|
+
);
|
|
2778
|
+
}
|
|
2779
|
+
validatePrivateKey(privateKey);
|
|
2780
|
+
this.privateKey = privateKey;
|
|
2781
|
+
this.account = (0, import_accounts7.privateKeyToAccount)(privateKey);
|
|
2782
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL6;
|
|
2783
|
+
validateApiUrl(apiUrl);
|
|
2784
|
+
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2785
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT6;
|
|
2786
|
+
}
|
|
2585
2787
|
async search(query, options) {
|
|
2586
2788
|
if (!query || query.length > 1e3) {
|
|
2587
2789
|
throw new Error("query must be 1-1000 characters");
|
|
@@ -2694,9 +2896,9 @@ var SearchClient = class {
|
|
|
2694
2896
|
};
|
|
2695
2897
|
|
|
2696
2898
|
// src/x-client.ts
|
|
2697
|
-
var
|
|
2698
|
-
var
|
|
2699
|
-
var
|
|
2899
|
+
var import_accounts8 = require("viem/accounts");
|
|
2900
|
+
var DEFAULT_API_URL7 = "https://blockrun.ai/api";
|
|
2901
|
+
var DEFAULT_TIMEOUT7 = 6e4;
|
|
2700
2902
|
var XClient = class _XClient {
|
|
2701
2903
|
account;
|
|
2702
2904
|
privateKey;
|
|
@@ -2719,11 +2921,11 @@ var XClient = class _XClient {
|
|
|
2719
2921
|
}
|
|
2720
2922
|
validatePrivateKey(privateKey);
|
|
2721
2923
|
this.privateKey = privateKey;
|
|
2722
|
-
this.account = (0,
|
|
2723
|
-
const apiUrl = options.apiUrl ||
|
|
2924
|
+
this.account = (0, import_accounts8.privateKeyToAccount)(privateKey);
|
|
2925
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL7;
|
|
2724
2926
|
validateApiUrl(apiUrl);
|
|
2725
2927
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2726
|
-
this.timeout = options.timeout ||
|
|
2928
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT7;
|
|
2727
2929
|
}
|
|
2728
2930
|
// ───────── User endpoints ─────────
|
|
2729
2931
|
userLookup(usernames) {
|
|
@@ -2901,9 +3103,9 @@ var XClient = class _XClient {
|
|
|
2901
3103
|
};
|
|
2902
3104
|
|
|
2903
3105
|
// src/price.ts
|
|
2904
|
-
var
|
|
2905
|
-
var
|
|
2906
|
-
var
|
|
3106
|
+
var import_accounts9 = require("viem/accounts");
|
|
3107
|
+
var DEFAULT_API_URL8 = "https://blockrun.ai/api";
|
|
3108
|
+
var DEFAULT_TIMEOUT8 = 3e4;
|
|
2907
3109
|
var PriceClient = class {
|
|
2908
3110
|
account = null;
|
|
2909
3111
|
privateKey = null;
|
|
@@ -2921,12 +3123,12 @@ var PriceClient = class {
|
|
|
2921
3123
|
if (privateKey) {
|
|
2922
3124
|
validatePrivateKey(privateKey);
|
|
2923
3125
|
this.privateKey = privateKey;
|
|
2924
|
-
this.account = (0,
|
|
3126
|
+
this.account = (0, import_accounts9.privateKeyToAccount)(privateKey);
|
|
2925
3127
|
}
|
|
2926
|
-
const apiUrl = options.apiUrl ||
|
|
3128
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL8;
|
|
2927
3129
|
validateApiUrl(apiUrl);
|
|
2928
3130
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2929
|
-
this.timeout = options.timeout ||
|
|
3131
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT8;
|
|
2930
3132
|
}
|
|
2931
3133
|
async price(category, symbol, options) {
|
|
2932
3134
|
if (!symbol) throw new Error("symbol is required");
|
|
@@ -3105,7 +3307,7 @@ function buildUrl(base, query) {
|
|
|
3105
3307
|
}
|
|
3106
3308
|
|
|
3107
3309
|
// src/wallet.ts
|
|
3108
|
-
var
|
|
3310
|
+
var import_accounts10 = require("viem/accounts");
|
|
3109
3311
|
var fs2 = __toESM(require("fs"), 1);
|
|
3110
3312
|
var path2 = __toESM(require("path"), 1);
|
|
3111
3313
|
var os2 = __toESM(require("os"), 1);
|
|
@@ -3114,8 +3316,8 @@ var BASE_CHAIN_ID2 = "8453";
|
|
|
3114
3316
|
var WALLET_DIR = path2.join(os2.homedir(), ".blockrun");
|
|
3115
3317
|
var WALLET_FILE = path2.join(WALLET_DIR, ".session");
|
|
3116
3318
|
function createWallet() {
|
|
3117
|
-
const privateKey = (0,
|
|
3118
|
-
const account = (0,
|
|
3319
|
+
const privateKey = (0, import_accounts10.generatePrivateKey)();
|
|
3320
|
+
const account = (0, import_accounts10.privateKeyToAccount)(privateKey);
|
|
3119
3321
|
return {
|
|
3120
3322
|
address: account.address,
|
|
3121
3323
|
privateKey
|
|
@@ -3171,12 +3373,12 @@ function loadWallet() {
|
|
|
3171
3373
|
function getOrCreateWallet() {
|
|
3172
3374
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3173
3375
|
if (envKey) {
|
|
3174
|
-
const account = (0,
|
|
3376
|
+
const account = (0, import_accounts10.privateKeyToAccount)(envKey);
|
|
3175
3377
|
return { address: account.address, privateKey: envKey, isNew: false };
|
|
3176
3378
|
}
|
|
3177
3379
|
const fileKey = loadWallet();
|
|
3178
3380
|
if (fileKey) {
|
|
3179
|
-
const account = (0,
|
|
3381
|
+
const account = (0, import_accounts10.privateKeyToAccount)(fileKey);
|
|
3180
3382
|
return { address: account.address, privateKey: fileKey, isNew: false };
|
|
3181
3383
|
}
|
|
3182
3384
|
const { address, privateKey } = createWallet();
|
|
@@ -3186,11 +3388,11 @@ function getOrCreateWallet() {
|
|
|
3186
3388
|
function getWalletAddress() {
|
|
3187
3389
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3188
3390
|
if (envKey) {
|
|
3189
|
-
return (0,
|
|
3391
|
+
return (0, import_accounts10.privateKeyToAccount)(envKey).address;
|
|
3190
3392
|
}
|
|
3191
3393
|
const fileKey = loadWallet();
|
|
3192
3394
|
if (fileKey) {
|
|
3193
|
-
return (0,
|
|
3395
|
+
return (0, import_accounts10.privateKeyToAccount)(fileKey).address;
|
|
3194
3396
|
}
|
|
3195
3397
|
return null;
|
|
3196
3398
|
}
|
|
@@ -3370,7 +3572,7 @@ async function getOrCreateSolanaWallet() {
|
|
|
3370
3572
|
// src/solana-client.ts
|
|
3371
3573
|
var SOLANA_API_URL = "https://sol.blockrun.ai/api";
|
|
3372
3574
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
3373
|
-
var
|
|
3575
|
+
var DEFAULT_TIMEOUT9 = 6e4;
|
|
3374
3576
|
var SDK_VERSION2 = "0.3.0";
|
|
3375
3577
|
var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
|
|
3376
3578
|
var SolanaLLMClient = class {
|
|
@@ -3395,7 +3597,7 @@ var SolanaLLMClient = class {
|
|
|
3395
3597
|
validateApiUrl(apiUrl);
|
|
3396
3598
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3397
3599
|
this.rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
|
|
3398
|
-
this.timeout = options.timeout ||
|
|
3600
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT9;
|
|
3399
3601
|
}
|
|
3400
3602
|
/** Get Solana wallet address (public key in base58). */
|
|
3401
3603
|
async getWalletAddress() {
|
|
@@ -4302,7 +4504,7 @@ var OpenAI = class {
|
|
|
4302
4504
|
};
|
|
4303
4505
|
|
|
4304
4506
|
// src/anthropic-compat.ts
|
|
4305
|
-
var
|
|
4507
|
+
var import_accounts11 = require("viem/accounts");
|
|
4306
4508
|
var AnthropicClient = class {
|
|
4307
4509
|
_client = null;
|
|
4308
4510
|
_clientPromise = null;
|
|
@@ -4315,7 +4517,7 @@ var AnthropicClient = class {
|
|
|
4315
4517
|
const key = options.privateKey ?? wallet.privateKey;
|
|
4316
4518
|
validatePrivateKey(key);
|
|
4317
4519
|
this._privateKey = key;
|
|
4318
|
-
this._account = (0,
|
|
4520
|
+
this._account = (0, import_accounts11.privateKeyToAccount)(this._privateKey);
|
|
4319
4521
|
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
4320
4522
|
validateApiUrl(apiUrl);
|
|
4321
4523
|
this._apiUrl = apiUrl.replace(/\/$/, "");
|
|
@@ -4430,6 +4632,7 @@ var AnthropicClient = class {
|
|
|
4430
4632
|
USDC_BASE_CONTRACT,
|
|
4431
4633
|
USDC_SOLANA,
|
|
4432
4634
|
VideoClient,
|
|
4635
|
+
VoiceClient,
|
|
4433
4636
|
WALLET_DIR_PATH,
|
|
4434
4637
|
WALLET_FILE_PATH,
|
|
4435
4638
|
XClient,
|
package/dist/index.d.cts
CHANGED
|
@@ -383,6 +383,74 @@ interface MusicGenerateOptions {
|
|
|
383
383
|
/** Custom lyrics — cannot be used with instrumental: true */
|
|
384
384
|
lyrics?: string;
|
|
385
385
|
}
|
|
386
|
+
/** Built-in Bland.ai voice presets. Any string is accepted (custom voice IDs work too). */
|
|
387
|
+
type VoicePreset = "nat" | "josh" | "maya" | "june" | "paige" | "derek" | "florian";
|
|
388
|
+
/** Bland.ai conversation model tier. */
|
|
389
|
+
type CallModel = "base" | "enhanced" | "turbo";
|
|
390
|
+
interface VoiceClientOptions {
|
|
391
|
+
/** EVM wallet private key (hex string starting with 0x) */
|
|
392
|
+
privateKey?: `0x${string}` | string;
|
|
393
|
+
/** API endpoint URL (default: https://blockrun.ai/api) */
|
|
394
|
+
apiUrl?: string;
|
|
395
|
+
/** Request timeout in milliseconds (default: 60000 — initiation only) */
|
|
396
|
+
timeout?: number;
|
|
397
|
+
}
|
|
398
|
+
interface CallOptions {
|
|
399
|
+
/** Destination phone number in E.164 format (e.g. "+14155552671"). US + Canada. */
|
|
400
|
+
to: string;
|
|
401
|
+
/** What the AI agent should do on the call. 10–4000 chars. */
|
|
402
|
+
task: string;
|
|
403
|
+
/** Your provisioned BlockRun caller-ID number (E.164). Must be wallet-owned. */
|
|
404
|
+
from?: string;
|
|
405
|
+
/** Voice preset or any Bland.ai voice ID. */
|
|
406
|
+
voice?: VoicePreset | string;
|
|
407
|
+
/** Maximum call length in minutes (1–30, default 5). */
|
|
408
|
+
max_duration?: number;
|
|
409
|
+
/** BCP-47 language code for STT/TTS (default "en-US"). */
|
|
410
|
+
language?: string;
|
|
411
|
+
/** Optional opening line spoken by the agent. */
|
|
412
|
+
first_sentence?: string;
|
|
413
|
+
/** If true, wait for the recipient to speak first. */
|
|
414
|
+
wait_for_greeting?: boolean;
|
|
415
|
+
/** Sensitivity for detecting recipient interruption (50–500 ms). */
|
|
416
|
+
interruption_threshold?: number;
|
|
417
|
+
/** Conversation model. */
|
|
418
|
+
model?: CallModel;
|
|
419
|
+
}
|
|
420
|
+
interface CallInitiatedResponse {
|
|
421
|
+
call_id: string;
|
|
422
|
+
status: string;
|
|
423
|
+
poll_url: string;
|
|
424
|
+
message?: string;
|
|
425
|
+
/** On-chain payment receipt (Base tx hash). */
|
|
426
|
+
txHash?: string;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Bland.ai call status payload. Returned from getStatus.
|
|
430
|
+
* Most fields are populated only after the call ends.
|
|
431
|
+
*/
|
|
432
|
+
interface CallStatusResponse {
|
|
433
|
+
call_id?: string;
|
|
434
|
+
status?: string;
|
|
435
|
+
to?: string;
|
|
436
|
+
from?: string;
|
|
437
|
+
/** ISO timestamp call started, or null while queued. */
|
|
438
|
+
started_at?: string | null;
|
|
439
|
+
/** ISO timestamp call ended, or null while in progress. */
|
|
440
|
+
ended_at?: string | null;
|
|
441
|
+
/** Total call length in seconds, once completed. */
|
|
442
|
+
call_length?: number;
|
|
443
|
+
/** URL to the call recording (mp3/wav). */
|
|
444
|
+
recording_url?: string | null;
|
|
445
|
+
/** Full text transcript of the call. */
|
|
446
|
+
concatenated_transcript?: string | null;
|
|
447
|
+
/** Per-turn transcript array. Shape comes from Bland.ai. */
|
|
448
|
+
transcripts?: Array<Record<string, unknown>>;
|
|
449
|
+
/** Why the call ended ("user_hangup", "agent_hangup", "timeout", …). */
|
|
450
|
+
ended_reason?: string | null;
|
|
451
|
+
/** Pass-through for anything Bland.ai adds. */
|
|
452
|
+
[key: string]: unknown;
|
|
453
|
+
}
|
|
386
454
|
interface VideoClip {
|
|
387
455
|
/** Permanent blockrun-hosted URL (falls back to upstream if backup fails) */
|
|
388
456
|
url: string;
|
|
@@ -1416,6 +1484,83 @@ declare class VideoClient {
|
|
|
1416
1484
|
getSpending(): Spending;
|
|
1417
1485
|
}
|
|
1418
1486
|
|
|
1487
|
+
/**
|
|
1488
|
+
* BlockRun Voice Call Client - AI-powered outbound phone calls via x402 micropayments.
|
|
1489
|
+
*
|
|
1490
|
+
* The AI agent calls a phone number (E.164) and conducts a real-time conversation
|
|
1491
|
+
* based on your 'task' instructions. STT, LLM, and TTS are handled upstream by
|
|
1492
|
+
* Bland.ai; BlockRun handles billing through x402.
|
|
1493
|
+
*
|
|
1494
|
+
* SECURITY NOTE - Private Key Handling:
|
|
1495
|
+
* Your private key NEVER leaves your machine. Here's what happens:
|
|
1496
|
+
* 1. Key stays local - only used to sign an EIP-712 typed data message
|
|
1497
|
+
* 2. Only the SIGNATURE is sent in the PAYMENT-SIGNATURE header
|
|
1498
|
+
* 3. BlockRun verifies the signature on-chain via Coinbase CDP facilitator
|
|
1499
|
+
*
|
|
1500
|
+
* Usage:
|
|
1501
|
+
* import { VoiceClient } from '@blockrun/llm';
|
|
1502
|
+
*
|
|
1503
|
+
* const client = new VoiceClient({ privateKey: '0x...' });
|
|
1504
|
+
*
|
|
1505
|
+
* // Initiate a call (paid, $0.54)
|
|
1506
|
+
* const result = await client.call({
|
|
1507
|
+
* to: '+14155552671',
|
|
1508
|
+
* task: 'You are a friendly assistant calling to confirm a 3pm dentist appointment.',
|
|
1509
|
+
* max_duration: 5,
|
|
1510
|
+
* });
|
|
1511
|
+
* console.log(result.call_id);
|
|
1512
|
+
*
|
|
1513
|
+
* // Poll status, transcript, recording (free)
|
|
1514
|
+
* const status = await client.getStatus(result.call_id);
|
|
1515
|
+
* console.log(status);
|
|
1516
|
+
*/
|
|
1517
|
+
|
|
1518
|
+
/**
|
|
1519
|
+
* BlockRun Voice Call Client.
|
|
1520
|
+
*
|
|
1521
|
+
* Initiates AI-powered outbound phone calls with automatic x402 micropayments
|
|
1522
|
+
* on Base chain.
|
|
1523
|
+
*
|
|
1524
|
+
* Pricing: $0.54 per call (regardless of duration up to max_duration).
|
|
1525
|
+
* Status polling is free.
|
|
1526
|
+
*/
|
|
1527
|
+
declare class VoiceClient {
|
|
1528
|
+
private account;
|
|
1529
|
+
private privateKey;
|
|
1530
|
+
private apiUrl;
|
|
1531
|
+
private timeout;
|
|
1532
|
+
private sessionTotalUsd;
|
|
1533
|
+
private sessionCalls;
|
|
1534
|
+
constructor(options?: VoiceClientOptions);
|
|
1535
|
+
/**
|
|
1536
|
+
* Initiate an AI-powered outbound phone call.
|
|
1537
|
+
*
|
|
1538
|
+
* Pricing: $0.54 per call. Returns immediately once the call is queued —
|
|
1539
|
+
* poll getStatus() for transcript and recording.
|
|
1540
|
+
*
|
|
1541
|
+
* @example
|
|
1542
|
+
* const r = await client.call({
|
|
1543
|
+
* to: '+14155552671',
|
|
1544
|
+
* task: 'Confirm the user wants to reschedule to Tuesday 2pm.',
|
|
1545
|
+
* voice: 'maya',
|
|
1546
|
+
* max_duration: 3,
|
|
1547
|
+
* });
|
|
1548
|
+
*/
|
|
1549
|
+
call(options: CallOptions): Promise<CallInitiatedResponse>;
|
|
1550
|
+
/**
|
|
1551
|
+
* Poll the status of an in-progress or completed call. Free — no payment.
|
|
1552
|
+
*
|
|
1553
|
+
* Returns Bland.ai's full call record: status, transcript, recording URL, etc.
|
|
1554
|
+
* Most fields populate only once the call ends.
|
|
1555
|
+
*/
|
|
1556
|
+
getStatus(callId: string): Promise<CallStatusResponse>;
|
|
1557
|
+
private requestWithPayment;
|
|
1558
|
+
private handlePaymentAndRetry;
|
|
1559
|
+
private fetchWithTimeout;
|
|
1560
|
+
getWalletAddress(): string;
|
|
1561
|
+
getSpending(): Spending;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1419
1564
|
/**
|
|
1420
1565
|
* BlockRun Search Client - Standalone Grok Live Search via x402 micropayments.
|
|
1421
1566
|
*
|
|
@@ -2193,4 +2338,4 @@ declare function validateTemperature(temperature?: number): void;
|
|
|
2193
2338
|
*/
|
|
2194
2339
|
declare function validateTopP(topP?: number): void;
|
|
2195
2340
|
|
|
2196
|
-
export { APIError, AnthropicClient, type AudioModel, type AudioTrack, BASE_CHAIN_ID, type BarResolution, 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, type HistoryOptions, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, type ImageGenerateOptions, type ImageModel, type ImageResponse, KNOWN_PROVIDERS, LLMClient, type LLMClientOptions, type ListOptions, type MarketSession, 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 PriceBar, type PriceCategory, PriceClient, type PriceClientOptions, type PriceHistoryResponse, type PriceOptions, type PricePoint, type RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, SearchClient, type SearchClientOptions, type SearchOptions, type SearchParameters, type SearchResult, type SearchSource, type SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type SpendingReport, type StockMarket, type SymbolListResponse, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, VideoClient, type VideoClientOptions, type VideoClip, type VideoGenerateOptions, type VideoModel, type VideoResponse, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XArticlesRisingResponse, type XAuthorAnalyticsResponse, XClient, type XClientOptions, type XCompareAuthorsResponse, type XFollower, type XFollowersResponse, type XFollowingsResponse, type XMentionsOptions, type XMentionsResponse, type XSearchOptions, type XSearchResponse, type XSearchSource, type XTrendingResponse, type XTweet, type XTweetLookupResponse, type XTweetRepliesOptions, type XTweetRepliesResponse, type XTweetThreadResponse, type XTweetsResponse, type XUser, type XUserInfoResponse, type XUserLookupResponse, type XUserTweetsOptions, 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, validateMaxTokens, validateModel, validateTemperature, validateTopP };
|
|
2341
|
+
export { APIError, AnthropicClient, type AudioModel, type AudioTrack, BASE_CHAIN_ID, type BarResolution, type BlockRunAnthropicOptions, BlockrunError, type CallInitiatedResponse, type CallModel, type CallOptions, type CallStatusResponse, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatResponseWithCost, type ChatUsage, type CostEntry, type CostEstimate, type CreatePaymentOptions, type FunctionCall, type FunctionDefinition, type HistoryOptions, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, type ImageGenerateOptions, type ImageModel, type ImageResponse, KNOWN_PROVIDERS, LLMClient, type LLMClientOptions, type ListOptions, type MarketSession, 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 PriceBar, type PriceCategory, PriceClient, type PriceClientOptions, type PriceHistoryResponse, type PriceOptions, type PricePoint, type RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, SearchClient, type SearchClientOptions, type SearchOptions, type SearchParameters, type SearchResult, type SearchSource, type SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type SpendingReport, type StockMarket, type SymbolListResponse, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, VideoClient, type VideoClientOptions, type VideoClip, type VideoGenerateOptions, type VideoModel, type VideoResponse, VoiceClient, type VoiceClientOptions, type VoicePreset, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XArticlesRisingResponse, type XAuthorAnalyticsResponse, XClient, type XClientOptions, type XCompareAuthorsResponse, type XFollower, type XFollowersResponse, type XFollowingsResponse, type XMentionsOptions, type XMentionsResponse, type XSearchOptions, type XSearchResponse, type XSearchSource, type XTrendingResponse, type XTweet, type XTweetLookupResponse, type XTweetRepliesOptions, type XTweetRepliesResponse, type XTweetThreadResponse, type XTweetsResponse, type XUser, type XUserInfoResponse, type XUserLookupResponse, type XUserTweetsOptions, 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, validateMaxTokens, validateModel, validateTemperature, validateTopP };
|
package/dist/index.d.ts
CHANGED
|
@@ -383,6 +383,74 @@ interface MusicGenerateOptions {
|
|
|
383
383
|
/** Custom lyrics — cannot be used with instrumental: true */
|
|
384
384
|
lyrics?: string;
|
|
385
385
|
}
|
|
386
|
+
/** Built-in Bland.ai voice presets. Any string is accepted (custom voice IDs work too). */
|
|
387
|
+
type VoicePreset = "nat" | "josh" | "maya" | "june" | "paige" | "derek" | "florian";
|
|
388
|
+
/** Bland.ai conversation model tier. */
|
|
389
|
+
type CallModel = "base" | "enhanced" | "turbo";
|
|
390
|
+
interface VoiceClientOptions {
|
|
391
|
+
/** EVM wallet private key (hex string starting with 0x) */
|
|
392
|
+
privateKey?: `0x${string}` | string;
|
|
393
|
+
/** API endpoint URL (default: https://blockrun.ai/api) */
|
|
394
|
+
apiUrl?: string;
|
|
395
|
+
/** Request timeout in milliseconds (default: 60000 — initiation only) */
|
|
396
|
+
timeout?: number;
|
|
397
|
+
}
|
|
398
|
+
interface CallOptions {
|
|
399
|
+
/** Destination phone number in E.164 format (e.g. "+14155552671"). US + Canada. */
|
|
400
|
+
to: string;
|
|
401
|
+
/** What the AI agent should do on the call. 10–4000 chars. */
|
|
402
|
+
task: string;
|
|
403
|
+
/** Your provisioned BlockRun caller-ID number (E.164). Must be wallet-owned. */
|
|
404
|
+
from?: string;
|
|
405
|
+
/** Voice preset or any Bland.ai voice ID. */
|
|
406
|
+
voice?: VoicePreset | string;
|
|
407
|
+
/** Maximum call length in minutes (1–30, default 5). */
|
|
408
|
+
max_duration?: number;
|
|
409
|
+
/** BCP-47 language code for STT/TTS (default "en-US"). */
|
|
410
|
+
language?: string;
|
|
411
|
+
/** Optional opening line spoken by the agent. */
|
|
412
|
+
first_sentence?: string;
|
|
413
|
+
/** If true, wait for the recipient to speak first. */
|
|
414
|
+
wait_for_greeting?: boolean;
|
|
415
|
+
/** Sensitivity for detecting recipient interruption (50–500 ms). */
|
|
416
|
+
interruption_threshold?: number;
|
|
417
|
+
/** Conversation model. */
|
|
418
|
+
model?: CallModel;
|
|
419
|
+
}
|
|
420
|
+
interface CallInitiatedResponse {
|
|
421
|
+
call_id: string;
|
|
422
|
+
status: string;
|
|
423
|
+
poll_url: string;
|
|
424
|
+
message?: string;
|
|
425
|
+
/** On-chain payment receipt (Base tx hash). */
|
|
426
|
+
txHash?: string;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Bland.ai call status payload. Returned from getStatus.
|
|
430
|
+
* Most fields are populated only after the call ends.
|
|
431
|
+
*/
|
|
432
|
+
interface CallStatusResponse {
|
|
433
|
+
call_id?: string;
|
|
434
|
+
status?: string;
|
|
435
|
+
to?: string;
|
|
436
|
+
from?: string;
|
|
437
|
+
/** ISO timestamp call started, or null while queued. */
|
|
438
|
+
started_at?: string | null;
|
|
439
|
+
/** ISO timestamp call ended, or null while in progress. */
|
|
440
|
+
ended_at?: string | null;
|
|
441
|
+
/** Total call length in seconds, once completed. */
|
|
442
|
+
call_length?: number;
|
|
443
|
+
/** URL to the call recording (mp3/wav). */
|
|
444
|
+
recording_url?: string | null;
|
|
445
|
+
/** Full text transcript of the call. */
|
|
446
|
+
concatenated_transcript?: string | null;
|
|
447
|
+
/** Per-turn transcript array. Shape comes from Bland.ai. */
|
|
448
|
+
transcripts?: Array<Record<string, unknown>>;
|
|
449
|
+
/** Why the call ended ("user_hangup", "agent_hangup", "timeout", …). */
|
|
450
|
+
ended_reason?: string | null;
|
|
451
|
+
/** Pass-through for anything Bland.ai adds. */
|
|
452
|
+
[key: string]: unknown;
|
|
453
|
+
}
|
|
386
454
|
interface VideoClip {
|
|
387
455
|
/** Permanent blockrun-hosted URL (falls back to upstream if backup fails) */
|
|
388
456
|
url: string;
|
|
@@ -1416,6 +1484,83 @@ declare class VideoClient {
|
|
|
1416
1484
|
getSpending(): Spending;
|
|
1417
1485
|
}
|
|
1418
1486
|
|
|
1487
|
+
/**
|
|
1488
|
+
* BlockRun Voice Call Client - AI-powered outbound phone calls via x402 micropayments.
|
|
1489
|
+
*
|
|
1490
|
+
* The AI agent calls a phone number (E.164) and conducts a real-time conversation
|
|
1491
|
+
* based on your 'task' instructions. STT, LLM, and TTS are handled upstream by
|
|
1492
|
+
* Bland.ai; BlockRun handles billing through x402.
|
|
1493
|
+
*
|
|
1494
|
+
* SECURITY NOTE - Private Key Handling:
|
|
1495
|
+
* Your private key NEVER leaves your machine. Here's what happens:
|
|
1496
|
+
* 1. Key stays local - only used to sign an EIP-712 typed data message
|
|
1497
|
+
* 2. Only the SIGNATURE is sent in the PAYMENT-SIGNATURE header
|
|
1498
|
+
* 3. BlockRun verifies the signature on-chain via Coinbase CDP facilitator
|
|
1499
|
+
*
|
|
1500
|
+
* Usage:
|
|
1501
|
+
* import { VoiceClient } from '@blockrun/llm';
|
|
1502
|
+
*
|
|
1503
|
+
* const client = new VoiceClient({ privateKey: '0x...' });
|
|
1504
|
+
*
|
|
1505
|
+
* // Initiate a call (paid, $0.54)
|
|
1506
|
+
* const result = await client.call({
|
|
1507
|
+
* to: '+14155552671',
|
|
1508
|
+
* task: 'You are a friendly assistant calling to confirm a 3pm dentist appointment.',
|
|
1509
|
+
* max_duration: 5,
|
|
1510
|
+
* });
|
|
1511
|
+
* console.log(result.call_id);
|
|
1512
|
+
*
|
|
1513
|
+
* // Poll status, transcript, recording (free)
|
|
1514
|
+
* const status = await client.getStatus(result.call_id);
|
|
1515
|
+
* console.log(status);
|
|
1516
|
+
*/
|
|
1517
|
+
|
|
1518
|
+
/**
|
|
1519
|
+
* BlockRun Voice Call Client.
|
|
1520
|
+
*
|
|
1521
|
+
* Initiates AI-powered outbound phone calls with automatic x402 micropayments
|
|
1522
|
+
* on Base chain.
|
|
1523
|
+
*
|
|
1524
|
+
* Pricing: $0.54 per call (regardless of duration up to max_duration).
|
|
1525
|
+
* Status polling is free.
|
|
1526
|
+
*/
|
|
1527
|
+
declare class VoiceClient {
|
|
1528
|
+
private account;
|
|
1529
|
+
private privateKey;
|
|
1530
|
+
private apiUrl;
|
|
1531
|
+
private timeout;
|
|
1532
|
+
private sessionTotalUsd;
|
|
1533
|
+
private sessionCalls;
|
|
1534
|
+
constructor(options?: VoiceClientOptions);
|
|
1535
|
+
/**
|
|
1536
|
+
* Initiate an AI-powered outbound phone call.
|
|
1537
|
+
*
|
|
1538
|
+
* Pricing: $0.54 per call. Returns immediately once the call is queued —
|
|
1539
|
+
* poll getStatus() for transcript and recording.
|
|
1540
|
+
*
|
|
1541
|
+
* @example
|
|
1542
|
+
* const r = await client.call({
|
|
1543
|
+
* to: '+14155552671',
|
|
1544
|
+
* task: 'Confirm the user wants to reschedule to Tuesday 2pm.',
|
|
1545
|
+
* voice: 'maya',
|
|
1546
|
+
* max_duration: 3,
|
|
1547
|
+
* });
|
|
1548
|
+
*/
|
|
1549
|
+
call(options: CallOptions): Promise<CallInitiatedResponse>;
|
|
1550
|
+
/**
|
|
1551
|
+
* Poll the status of an in-progress or completed call. Free — no payment.
|
|
1552
|
+
*
|
|
1553
|
+
* Returns Bland.ai's full call record: status, transcript, recording URL, etc.
|
|
1554
|
+
* Most fields populate only once the call ends.
|
|
1555
|
+
*/
|
|
1556
|
+
getStatus(callId: string): Promise<CallStatusResponse>;
|
|
1557
|
+
private requestWithPayment;
|
|
1558
|
+
private handlePaymentAndRetry;
|
|
1559
|
+
private fetchWithTimeout;
|
|
1560
|
+
getWalletAddress(): string;
|
|
1561
|
+
getSpending(): Spending;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1419
1564
|
/**
|
|
1420
1565
|
* BlockRun Search Client - Standalone Grok Live Search via x402 micropayments.
|
|
1421
1566
|
*
|
|
@@ -2193,4 +2338,4 @@ declare function validateTemperature(temperature?: number): void;
|
|
|
2193
2338
|
*/
|
|
2194
2339
|
declare function validateTopP(topP?: number): void;
|
|
2195
2340
|
|
|
2196
|
-
export { APIError, AnthropicClient, type AudioModel, type AudioTrack, BASE_CHAIN_ID, type BarResolution, 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, type HistoryOptions, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, type ImageGenerateOptions, type ImageModel, type ImageResponse, KNOWN_PROVIDERS, LLMClient, type LLMClientOptions, type ListOptions, type MarketSession, 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 PriceBar, type PriceCategory, PriceClient, type PriceClientOptions, type PriceHistoryResponse, type PriceOptions, type PricePoint, type RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, SearchClient, type SearchClientOptions, type SearchOptions, type SearchParameters, type SearchResult, type SearchSource, type SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type SpendingReport, type StockMarket, type SymbolListResponse, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, VideoClient, type VideoClientOptions, type VideoClip, type VideoGenerateOptions, type VideoModel, type VideoResponse, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XArticlesRisingResponse, type XAuthorAnalyticsResponse, XClient, type XClientOptions, type XCompareAuthorsResponse, type XFollower, type XFollowersResponse, type XFollowingsResponse, type XMentionsOptions, type XMentionsResponse, type XSearchOptions, type XSearchResponse, type XSearchSource, type XTrendingResponse, type XTweet, type XTweetLookupResponse, type XTweetRepliesOptions, type XTweetRepliesResponse, type XTweetThreadResponse, type XTweetsResponse, type XUser, type XUserInfoResponse, type XUserLookupResponse, type XUserTweetsOptions, 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, validateMaxTokens, validateModel, validateTemperature, validateTopP };
|
|
2341
|
+
export { APIError, AnthropicClient, type AudioModel, type AudioTrack, BASE_CHAIN_ID, type BarResolution, type BlockRunAnthropicOptions, BlockrunError, type CallInitiatedResponse, type CallModel, type CallOptions, type CallStatusResponse, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatResponseWithCost, type ChatUsage, type CostEntry, type CostEstimate, type CreatePaymentOptions, type FunctionCall, type FunctionDefinition, type HistoryOptions, ImageClient, type ImageClientOptions, type ImageData, type ImageEditOptions, type ImageGenerateOptions, type ImageModel, type ImageResponse, KNOWN_PROVIDERS, LLMClient, type LLMClientOptions, type ListOptions, type MarketSession, 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 PriceBar, type PriceCategory, PriceClient, type PriceClientOptions, type PriceHistoryResponse, type PriceOptions, type PricePoint, type RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, SearchClient, type SearchClientOptions, type SearchOptions, type SearchParameters, type SearchResult, type SearchSource, type SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type SpendingReport, type StockMarket, type SymbolListResponse, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, VideoClient, type VideoClientOptions, type VideoClip, type VideoGenerateOptions, type VideoModel, type VideoResponse, VoiceClient, type VoiceClientOptions, type VoicePreset, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XArticlesRisingResponse, type XAuthorAnalyticsResponse, XClient, type XClientOptions, type XCompareAuthorsResponse, type XFollower, type XFollowersResponse, type XFollowingsResponse, type XMentionsOptions, type XMentionsResponse, type XSearchOptions, type XSearchResponse, type XSearchSource, type XTrendingResponse, type XTweet, type XTweetLookupResponse, type XTweetRepliesOptions, type XTweetRepliesResponse, type XTweetThreadResponse, type XTweetsResponse, type XUser, type XUserInfoResponse, type XUserLookupResponse, type XUserTweetsOptions, 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, validateMaxTokens, validateModel, validateTemperature, validateTopP };
|
package/dist/index.js
CHANGED
|
@@ -2461,15 +2461,19 @@ var VideoClient = class {
|
|
|
2461
2461
|
}
|
|
2462
2462
|
};
|
|
2463
2463
|
|
|
2464
|
-
// src/
|
|
2464
|
+
// src/voice.ts
|
|
2465
2465
|
import { privateKeyToAccount as privateKeyToAccount5 } from "viem/accounts";
|
|
2466
2466
|
var DEFAULT_API_URL5 = "https://blockrun.ai/api";
|
|
2467
2467
|
var DEFAULT_TIMEOUT5 = 6e4;
|
|
2468
|
-
var
|
|
2468
|
+
var CALL_PRICE_USD = 0.54;
|
|
2469
|
+
var VALID_MODELS = /* @__PURE__ */ new Set(["base", "enhanced", "turbo"]);
|
|
2470
|
+
var VoiceClient = class {
|
|
2469
2471
|
account;
|
|
2470
2472
|
privateKey;
|
|
2471
2473
|
apiUrl;
|
|
2472
2474
|
timeout;
|
|
2475
|
+
sessionTotalUsd = 0;
|
|
2476
|
+
sessionCalls = 0;
|
|
2473
2477
|
constructor(options = {}) {
|
|
2474
2478
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
2475
2479
|
const privateKey = options.privateKey || envKey;
|
|
@@ -2486,6 +2490,203 @@ var SearchClient = class {
|
|
|
2486
2490
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2487
2491
|
this.timeout = options.timeout || DEFAULT_TIMEOUT5;
|
|
2488
2492
|
}
|
|
2493
|
+
/**
|
|
2494
|
+
* Initiate an AI-powered outbound phone call.
|
|
2495
|
+
*
|
|
2496
|
+
* Pricing: $0.54 per call. Returns immediately once the call is queued —
|
|
2497
|
+
* poll getStatus() for transcript and recording.
|
|
2498
|
+
*
|
|
2499
|
+
* @example
|
|
2500
|
+
* const r = await client.call({
|
|
2501
|
+
* to: '+14155552671',
|
|
2502
|
+
* task: 'Confirm the user wants to reschedule to Tuesday 2pm.',
|
|
2503
|
+
* voice: 'maya',
|
|
2504
|
+
* max_duration: 3,
|
|
2505
|
+
* });
|
|
2506
|
+
*/
|
|
2507
|
+
async call(options) {
|
|
2508
|
+
if (!options.to || !options.to.trim()) {
|
|
2509
|
+
throw new Error("'to' phone number is required (E.164 format)");
|
|
2510
|
+
}
|
|
2511
|
+
const task = options.task?.trim() ?? "";
|
|
2512
|
+
if (task.length < 10) {
|
|
2513
|
+
throw new Error("'task' must be at least 10 characters");
|
|
2514
|
+
}
|
|
2515
|
+
if (task.length > 4e3) {
|
|
2516
|
+
throw new Error("'task' must be at most 4000 characters");
|
|
2517
|
+
}
|
|
2518
|
+
const maxDuration = options.max_duration ?? 5;
|
|
2519
|
+
if (maxDuration < 1 || maxDuration > 30) {
|
|
2520
|
+
throw new Error("max_duration must be between 1 and 30 minutes");
|
|
2521
|
+
}
|
|
2522
|
+
if (options.model && !VALID_MODELS.has(options.model)) {
|
|
2523
|
+
throw new Error("model must be 'base' | 'enhanced' | 'turbo'");
|
|
2524
|
+
}
|
|
2525
|
+
if (options.interruption_threshold !== void 0 && (options.interruption_threshold < 50 || options.interruption_threshold > 500)) {
|
|
2526
|
+
throw new Error("interruption_threshold must be between 50 and 500");
|
|
2527
|
+
}
|
|
2528
|
+
const body = {
|
|
2529
|
+
to: options.to.trim(),
|
|
2530
|
+
task,
|
|
2531
|
+
max_duration: maxDuration,
|
|
2532
|
+
language: options.language ?? "en-US"
|
|
2533
|
+
};
|
|
2534
|
+
if (options.from) body.from = options.from.trim();
|
|
2535
|
+
if (options.voice) body.voice = options.voice;
|
|
2536
|
+
if (options.first_sentence) body.first_sentence = options.first_sentence.trim();
|
|
2537
|
+
if (options.wait_for_greeting !== void 0) body.wait_for_greeting = options.wait_for_greeting;
|
|
2538
|
+
if (options.interruption_threshold !== void 0) body.interruption_threshold = options.interruption_threshold;
|
|
2539
|
+
if (options.model) body.model = options.model;
|
|
2540
|
+
return this.requestWithPayment("/v1/voice/call", body);
|
|
2541
|
+
}
|
|
2542
|
+
/**
|
|
2543
|
+
* Poll the status of an in-progress or completed call. Free — no payment.
|
|
2544
|
+
*
|
|
2545
|
+
* Returns Bland.ai's full call record: status, transcript, recording URL, etc.
|
|
2546
|
+
* Most fields populate only once the call ends.
|
|
2547
|
+
*/
|
|
2548
|
+
async getStatus(callId) {
|
|
2549
|
+
if (!callId || !callId.trim()) {
|
|
2550
|
+
throw new Error("callId is required");
|
|
2551
|
+
}
|
|
2552
|
+
const url = `${this.apiUrl}/v1/voice/call/${encodeURIComponent(callId.trim())}`;
|
|
2553
|
+
const response = await this.fetchWithTimeout(url, {
|
|
2554
|
+
method: "GET",
|
|
2555
|
+
headers: { Accept: "application/json" }
|
|
2556
|
+
});
|
|
2557
|
+
if (response.status === 404) {
|
|
2558
|
+
throw new APIError(`Call not found: ${callId}`, 404, { call_id: callId });
|
|
2559
|
+
}
|
|
2560
|
+
if (!response.ok) {
|
|
2561
|
+
let errorBody;
|
|
2562
|
+
try {
|
|
2563
|
+
errorBody = await response.json();
|
|
2564
|
+
} catch {
|
|
2565
|
+
errorBody = { error: "Request failed" };
|
|
2566
|
+
}
|
|
2567
|
+
throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
|
|
2568
|
+
}
|
|
2569
|
+
return response.json();
|
|
2570
|
+
}
|
|
2571
|
+
async requestWithPayment(endpoint, body) {
|
|
2572
|
+
const url = `${this.apiUrl}${endpoint}`;
|
|
2573
|
+
const response = await this.fetchWithTimeout(url, {
|
|
2574
|
+
method: "POST",
|
|
2575
|
+
headers: { "Content-Type": "application/json" },
|
|
2576
|
+
body: JSON.stringify(body)
|
|
2577
|
+
});
|
|
2578
|
+
if (response.status === 402) {
|
|
2579
|
+
return this.handlePaymentAndRetry(url, body, response);
|
|
2580
|
+
}
|
|
2581
|
+
if (!response.ok) {
|
|
2582
|
+
let errorBody;
|
|
2583
|
+
try {
|
|
2584
|
+
errorBody = await response.json();
|
|
2585
|
+
} catch {
|
|
2586
|
+
errorBody = { error: "Request failed" };
|
|
2587
|
+
}
|
|
2588
|
+
throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
|
|
2589
|
+
}
|
|
2590
|
+
return response.json();
|
|
2591
|
+
}
|
|
2592
|
+
async handlePaymentAndRetry(url, body, response) {
|
|
2593
|
+
let paymentHeader = response.headers.get("payment-required");
|
|
2594
|
+
if (!paymentHeader) {
|
|
2595
|
+
try {
|
|
2596
|
+
const respBody = await response.json();
|
|
2597
|
+
if (respBody.x402 || respBody.accepts) {
|
|
2598
|
+
paymentHeader = btoa(JSON.stringify(respBody));
|
|
2599
|
+
}
|
|
2600
|
+
} catch {
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
if (!paymentHeader) {
|
|
2604
|
+
throw new PaymentError("402 response but no payment requirements found");
|
|
2605
|
+
}
|
|
2606
|
+
const paymentRequired = parsePaymentRequired(paymentHeader);
|
|
2607
|
+
const details = extractPaymentDetails(paymentRequired);
|
|
2608
|
+
const paymentPayload = await createPaymentPayload(
|
|
2609
|
+
this.privateKey,
|
|
2610
|
+
this.account.address,
|
|
2611
|
+
details.recipient,
|
|
2612
|
+
details.amount,
|
|
2613
|
+
details.network || "eip155:8453",
|
|
2614
|
+
{
|
|
2615
|
+
resourceUrl: details.resource?.url || `${this.apiUrl}/v1/voice/call`,
|
|
2616
|
+
resourceDescription: details.resource?.description || "BlockRun Voice Call",
|
|
2617
|
+
maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
|
|
2618
|
+
extra: details.extra
|
|
2619
|
+
}
|
|
2620
|
+
);
|
|
2621
|
+
const retryResponse = await this.fetchWithTimeout(url, {
|
|
2622
|
+
method: "POST",
|
|
2623
|
+
headers: {
|
|
2624
|
+
"Content-Type": "application/json",
|
|
2625
|
+
"PAYMENT-SIGNATURE": paymentPayload
|
|
2626
|
+
},
|
|
2627
|
+
body: JSON.stringify(body)
|
|
2628
|
+
});
|
|
2629
|
+
if (retryResponse.status === 402) {
|
|
2630
|
+
throw new PaymentError("Payment was rejected. Check your wallet balance.");
|
|
2631
|
+
}
|
|
2632
|
+
if (!retryResponse.ok) {
|
|
2633
|
+
let errorBody;
|
|
2634
|
+
try {
|
|
2635
|
+
errorBody = await retryResponse.json();
|
|
2636
|
+
} catch {
|
|
2637
|
+
errorBody = { error: "Request failed" };
|
|
2638
|
+
}
|
|
2639
|
+
throw new APIError(`API error after payment: ${retryResponse.status}`, retryResponse.status, sanitizeErrorResponse(errorBody));
|
|
2640
|
+
}
|
|
2641
|
+
const data = await retryResponse.json();
|
|
2642
|
+
this.sessionCalls++;
|
|
2643
|
+
this.sessionTotalUsd += CALL_PRICE_USD;
|
|
2644
|
+
const txHash = retryResponse.headers.get("x-payment-receipt") || retryResponse.headers.get("X-Payment-Receipt");
|
|
2645
|
+
if (txHash) data.txHash = txHash;
|
|
2646
|
+
return data;
|
|
2647
|
+
}
|
|
2648
|
+
async fetchWithTimeout(url, options) {
|
|
2649
|
+
const controller = new AbortController();
|
|
2650
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
2651
|
+
try {
|
|
2652
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
2653
|
+
} finally {
|
|
2654
|
+
clearTimeout(timeoutId);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
getWalletAddress() {
|
|
2658
|
+
return this.account.address;
|
|
2659
|
+
}
|
|
2660
|
+
getSpending() {
|
|
2661
|
+
return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
|
|
2662
|
+
}
|
|
2663
|
+
};
|
|
2664
|
+
|
|
2665
|
+
// src/search.ts
|
|
2666
|
+
import { privateKeyToAccount as privateKeyToAccount6 } from "viem/accounts";
|
|
2667
|
+
var DEFAULT_API_URL6 = "https://blockrun.ai/api";
|
|
2668
|
+
var DEFAULT_TIMEOUT6 = 6e4;
|
|
2669
|
+
var SearchClient = class {
|
|
2670
|
+
account;
|
|
2671
|
+
privateKey;
|
|
2672
|
+
apiUrl;
|
|
2673
|
+
timeout;
|
|
2674
|
+
constructor(options = {}) {
|
|
2675
|
+
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
2676
|
+
const privateKey = options.privateKey || envKey;
|
|
2677
|
+
if (!privateKey) {
|
|
2678
|
+
throw new Error(
|
|
2679
|
+
"Private key required. Pass privateKey in options or set BLOCKRUN_WALLET_KEY environment variable."
|
|
2680
|
+
);
|
|
2681
|
+
}
|
|
2682
|
+
validatePrivateKey(privateKey);
|
|
2683
|
+
this.privateKey = privateKey;
|
|
2684
|
+
this.account = privateKeyToAccount6(privateKey);
|
|
2685
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL6;
|
|
2686
|
+
validateApiUrl(apiUrl);
|
|
2687
|
+
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2688
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT6;
|
|
2689
|
+
}
|
|
2489
2690
|
async search(query, options) {
|
|
2490
2691
|
if (!query || query.length > 1e3) {
|
|
2491
2692
|
throw new Error("query must be 1-1000 characters");
|
|
@@ -2598,9 +2799,9 @@ var SearchClient = class {
|
|
|
2598
2799
|
};
|
|
2599
2800
|
|
|
2600
2801
|
// src/x-client.ts
|
|
2601
|
-
import { privateKeyToAccount as
|
|
2602
|
-
var
|
|
2603
|
-
var
|
|
2802
|
+
import { privateKeyToAccount as privateKeyToAccount7 } from "viem/accounts";
|
|
2803
|
+
var DEFAULT_API_URL7 = "https://blockrun.ai/api";
|
|
2804
|
+
var DEFAULT_TIMEOUT7 = 6e4;
|
|
2604
2805
|
var XClient = class _XClient {
|
|
2605
2806
|
account;
|
|
2606
2807
|
privateKey;
|
|
@@ -2623,11 +2824,11 @@ var XClient = class _XClient {
|
|
|
2623
2824
|
}
|
|
2624
2825
|
validatePrivateKey(privateKey);
|
|
2625
2826
|
this.privateKey = privateKey;
|
|
2626
|
-
this.account =
|
|
2627
|
-
const apiUrl = options.apiUrl ||
|
|
2827
|
+
this.account = privateKeyToAccount7(privateKey);
|
|
2828
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL7;
|
|
2628
2829
|
validateApiUrl(apiUrl);
|
|
2629
2830
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2630
|
-
this.timeout = options.timeout ||
|
|
2831
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT7;
|
|
2631
2832
|
}
|
|
2632
2833
|
// ───────── User endpoints ─────────
|
|
2633
2834
|
userLookup(usernames) {
|
|
@@ -2805,9 +3006,9 @@ var XClient = class _XClient {
|
|
|
2805
3006
|
};
|
|
2806
3007
|
|
|
2807
3008
|
// src/price.ts
|
|
2808
|
-
import { privateKeyToAccount as
|
|
2809
|
-
var
|
|
2810
|
-
var
|
|
3009
|
+
import { privateKeyToAccount as privateKeyToAccount8 } from "viem/accounts";
|
|
3010
|
+
var DEFAULT_API_URL8 = "https://blockrun.ai/api";
|
|
3011
|
+
var DEFAULT_TIMEOUT8 = 3e4;
|
|
2811
3012
|
var PriceClient = class {
|
|
2812
3013
|
account = null;
|
|
2813
3014
|
privateKey = null;
|
|
@@ -2825,12 +3026,12 @@ var PriceClient = class {
|
|
|
2825
3026
|
if (privateKey) {
|
|
2826
3027
|
validatePrivateKey(privateKey);
|
|
2827
3028
|
this.privateKey = privateKey;
|
|
2828
|
-
this.account =
|
|
3029
|
+
this.account = privateKeyToAccount8(privateKey);
|
|
2829
3030
|
}
|
|
2830
|
-
const apiUrl = options.apiUrl ||
|
|
3031
|
+
const apiUrl = options.apiUrl || DEFAULT_API_URL8;
|
|
2831
3032
|
validateApiUrl(apiUrl);
|
|
2832
3033
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
2833
|
-
this.timeout = options.timeout ||
|
|
3034
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT8;
|
|
2834
3035
|
}
|
|
2835
3036
|
async price(category, symbol, options) {
|
|
2836
3037
|
if (!symbol) throw new Error("symbol is required");
|
|
@@ -3009,7 +3210,7 @@ function buildUrl(base, query) {
|
|
|
3009
3210
|
}
|
|
3010
3211
|
|
|
3011
3212
|
// src/wallet.ts
|
|
3012
|
-
import { privateKeyToAccount as
|
|
3213
|
+
import { privateKeyToAccount as privateKeyToAccount9, generatePrivateKey } from "viem/accounts";
|
|
3013
3214
|
import * as fs2 from "fs";
|
|
3014
3215
|
import * as path2 from "path";
|
|
3015
3216
|
import * as os2 from "os";
|
|
@@ -3019,7 +3220,7 @@ var WALLET_DIR = path2.join(os2.homedir(), ".blockrun");
|
|
|
3019
3220
|
var WALLET_FILE = path2.join(WALLET_DIR, ".session");
|
|
3020
3221
|
function createWallet() {
|
|
3021
3222
|
const privateKey = generatePrivateKey();
|
|
3022
|
-
const account =
|
|
3223
|
+
const account = privateKeyToAccount9(privateKey);
|
|
3023
3224
|
return {
|
|
3024
3225
|
address: account.address,
|
|
3025
3226
|
privateKey
|
|
@@ -3075,12 +3276,12 @@ function loadWallet() {
|
|
|
3075
3276
|
function getOrCreateWallet() {
|
|
3076
3277
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3077
3278
|
if (envKey) {
|
|
3078
|
-
const account =
|
|
3279
|
+
const account = privateKeyToAccount9(envKey);
|
|
3079
3280
|
return { address: account.address, privateKey: envKey, isNew: false };
|
|
3080
3281
|
}
|
|
3081
3282
|
const fileKey = loadWallet();
|
|
3082
3283
|
if (fileKey) {
|
|
3083
|
-
const account =
|
|
3284
|
+
const account = privateKeyToAccount9(fileKey);
|
|
3084
3285
|
return { address: account.address, privateKey: fileKey, isNew: false };
|
|
3085
3286
|
}
|
|
3086
3287
|
const { address, privateKey } = createWallet();
|
|
@@ -3090,11 +3291,11 @@ function getOrCreateWallet() {
|
|
|
3090
3291
|
function getWalletAddress() {
|
|
3091
3292
|
const envKey = typeof process !== "undefined" && process.env ? process.env.BLOCKRUN_WALLET_KEY || process.env.BASE_CHAIN_WALLET_KEY : void 0;
|
|
3092
3293
|
if (envKey) {
|
|
3093
|
-
return
|
|
3294
|
+
return privateKeyToAccount9(envKey).address;
|
|
3094
3295
|
}
|
|
3095
3296
|
const fileKey = loadWallet();
|
|
3096
3297
|
if (fileKey) {
|
|
3097
|
-
return
|
|
3298
|
+
return privateKeyToAccount9(fileKey).address;
|
|
3098
3299
|
}
|
|
3099
3300
|
return null;
|
|
3100
3301
|
}
|
|
@@ -3274,7 +3475,7 @@ async function getOrCreateSolanaWallet() {
|
|
|
3274
3475
|
// src/solana-client.ts
|
|
3275
3476
|
var SOLANA_API_URL = "https://sol.blockrun.ai/api";
|
|
3276
3477
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
3277
|
-
var
|
|
3478
|
+
var DEFAULT_TIMEOUT9 = 6e4;
|
|
3278
3479
|
var SDK_VERSION2 = "0.3.0";
|
|
3279
3480
|
var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
|
|
3280
3481
|
var SolanaLLMClient = class {
|
|
@@ -3299,7 +3500,7 @@ var SolanaLLMClient = class {
|
|
|
3299
3500
|
validateApiUrl(apiUrl);
|
|
3300
3501
|
this.apiUrl = apiUrl.replace(/\/$/, "");
|
|
3301
3502
|
this.rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
|
|
3302
|
-
this.timeout = options.timeout ||
|
|
3503
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT9;
|
|
3303
3504
|
}
|
|
3304
3505
|
/** Get Solana wallet address (public key in base58). */
|
|
3305
3506
|
async getWalletAddress() {
|
|
@@ -4206,7 +4407,7 @@ var OpenAI = class {
|
|
|
4206
4407
|
};
|
|
4207
4408
|
|
|
4208
4409
|
// src/anthropic-compat.ts
|
|
4209
|
-
import { privateKeyToAccount as
|
|
4410
|
+
import { privateKeyToAccount as privateKeyToAccount10 } from "viem/accounts";
|
|
4210
4411
|
var AnthropicClient = class {
|
|
4211
4412
|
_client = null;
|
|
4212
4413
|
_clientPromise = null;
|
|
@@ -4219,7 +4420,7 @@ var AnthropicClient = class {
|
|
|
4219
4420
|
const key = options.privateKey ?? wallet.privateKey;
|
|
4220
4421
|
validatePrivateKey(key);
|
|
4221
4422
|
this._privateKey = key;
|
|
4222
|
-
this._account =
|
|
4423
|
+
this._account = privateKeyToAccount10(this._privateKey);
|
|
4223
4424
|
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
4224
4425
|
validateApiUrl(apiUrl);
|
|
4225
4426
|
this._apiUrl = apiUrl.replace(/\/$/, "");
|
|
@@ -4333,6 +4534,7 @@ export {
|
|
|
4333
4534
|
USDC_BASE_CONTRACT,
|
|
4334
4535
|
USDC_SOLANA,
|
|
4335
4536
|
VideoClient,
|
|
4537
|
+
VoiceClient,
|
|
4336
4538
|
WALLET_DIR_PATH,
|
|
4337
4539
|
WALLET_FILE_PATH,
|
|
4338
4540
|
XClient,
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/llm",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "BlockRun SDK - Pay-per-request AI (LLM, Image, Video, Music) via x402 on Base and Solana",
|
|
5
|
+
"description": "BlockRun SDK - Pay-per-request AI (LLM, Image, Video, Music, Voice) 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",
|