@blockrun/llm 3.9.0 → 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,8 +1,183 @@
1
1
  import * as _anthropic_ai_sdk from '@anthropic-ai/sdk';
2
2
 
3
+ /**
4
+ * Smart Router Types
5
+ *
6
+ * Four classification tiers — REASONING is distinct from COMPLEX because
7
+ * reasoning tasks need different models (o3, gemini-pro) than general
8
+ * complex tasks (gpt-4o, sonnet-4).
9
+ *
10
+ * Scoring uses weighted float dimensions with sigmoid confidence calibration.
11
+ */
12
+ type Tier = "SIMPLE" | "MEDIUM" | "COMPLEX" | "REASONING";
13
+ type RoutingDecision$1 = {
14
+ model: string;
15
+ tier: Tier;
16
+ confidence: number;
17
+ method: "rules" | "llm" | "portfolio";
18
+ reasoning: string;
19
+ costEstimate: number;
20
+ baselineCost: number;
21
+ savings: number;
22
+ agenticScore?: number;
23
+ /** Which tier configs were used (auto/eco/premium/agentic) — avoids re-derivation in the host */
24
+ tierConfigs?: Record<Tier, TierConfig>;
25
+ /** Which routing profile was applied */
26
+ profile?: "auto" | "eco" | "premium" | "agentic";
27
+ /** Ordered, capability-eligible candidates. The first entry is `model`. */
28
+ candidates?: string[];
29
+ /** Explainable request classification used by the portfolio router. */
30
+ taskType?: TaskType;
31
+ /** Router implementation that made the selection. */
32
+ routerVersion?: "v2-rules" | "v3-portfolio";
33
+ /** Explainable local portfolio score breakdown, ordered with `candidates`. */
34
+ candidateScores?: Array<{
35
+ model: string;
36
+ score: number;
37
+ quality: number;
38
+ cost: number;
39
+ speed: number;
40
+ reliability: number;
41
+ }>;
42
+ };
43
+ type TaskType = "chat" | "extraction" | "code_edit" | "code_agent" | "tool_agent" | "tool_agent_parallel" | "debug" | "reasoning" | "reasoning_mcq" | "reasoning_math" | "long_context" | "vision";
44
+ type TierConfig = {
45
+ primary: string;
46
+ fallback: string[];
47
+ };
48
+ type ScoringConfig = {
49
+ tokenCountThresholds: {
50
+ simple: number;
51
+ complex: number;
52
+ };
53
+ codeKeywords: string[];
54
+ reasoningKeywords: string[];
55
+ simpleKeywords: string[];
56
+ technicalKeywords: string[];
57
+ creativeKeywords: string[];
58
+ imperativeVerbs: string[];
59
+ constraintIndicators: string[];
60
+ outputFormatKeywords: string[];
61
+ referenceKeywords: string[];
62
+ negationKeywords: string[];
63
+ domainSpecificKeywords: string[];
64
+ agenticTaskKeywords: string[];
65
+ dimensionWeights: Record<string, number>;
66
+ tierBoundaries: {
67
+ simpleMedium: number;
68
+ mediumComplex: number;
69
+ complexReasoning: number;
70
+ };
71
+ confidenceSteepness: number;
72
+ confidenceThreshold: number;
73
+ };
74
+ type ClassifierConfig = {
75
+ llmModel: string;
76
+ llmMaxTokens: number;
77
+ llmTemperature: number;
78
+ promptTruncationChars: number;
79
+ cacheTtlMs: number;
80
+ };
81
+ type OverridesConfig = {
82
+ maxTokensForceComplex: number;
83
+ structuredOutputMinTier: Tier;
84
+ ambiguousDefaultTier: Tier;
85
+ /**
86
+ * When enabled, prefer models optimized for agentic workflows.
87
+ * Agentic models continue autonomously with multi-step tasks
88
+ * instead of stopping and waiting for user input.
89
+ */
90
+ agenticMode?: boolean;
91
+ };
92
+ /**
93
+ * Time-windowed promotion that temporarily overrides tier routing.
94
+ * Active promotions are auto-applied; expired ones are ignored at runtime.
95
+ */
96
+ type Promotion = {
97
+ /** Human-readable label (e.g. "GLM-5 Launch Promo") */
98
+ name: string;
99
+ /** ISO date string, promotion starts (inclusive). e.g. "2026-04-01" */
100
+ startDate: string;
101
+ /** ISO date string, promotion ends (exclusive). e.g. "2026-04-15" */
102
+ endDate: string;
103
+ /** Partial tier overrides — merged into the active tier configs (primary/fallback) */
104
+ tierOverrides: Partial<Record<Tier, Partial<TierConfig>>>;
105
+ /** Which profiles this applies to. Default: all profiles. */
106
+ profiles?: Array<"auto" | "eco" | "premium" | "agentic">;
107
+ };
108
+ type RoutingConfig = {
109
+ version: string;
110
+ /** Enables a one-line rollback to the established V2 rules selector. */
111
+ strategy?: "rules" | "portfolio";
112
+ /**
113
+ * Locally recompute a comparison strategy without changing the model that
114
+ * actually serves the request. The host emits only decision metadata via
115
+ * `onShadowRouted`; it never persists prompt content or makes a second call.
116
+ */
117
+ shadow?: {
118
+ strategy: "rules" | "portfolio";
119
+ sampleRate?: number;
120
+ };
121
+ /** Calibratable local portfolio scoring weights; values are relative, not probabilities. */
122
+ portfolio?: {
123
+ auto: {
124
+ quality: number;
125
+ capability: number;
126
+ cost: number;
127
+ speed: number;
128
+ reliability: number;
129
+ legacy: number;
130
+ };
131
+ eco: {
132
+ quality: number;
133
+ capability: number;
134
+ cost: number;
135
+ speed: number;
136
+ reliability: number;
137
+ legacy: number;
138
+ };
139
+ premium: {
140
+ quality: number;
141
+ capability: number;
142
+ cost: number;
143
+ speed: number;
144
+ reliability: number;
145
+ legacy: number;
146
+ };
147
+ highStakesBoost: {
148
+ quality: number;
149
+ reliability: number;
150
+ };
151
+ latencySensitiveSpeedBoost: number;
152
+ /** A candidate materially below the best task affinity cannot win on cost alone. */
153
+ affinityFloorGap: {
154
+ auto: number;
155
+ eco: number;
156
+ premium: number;
157
+ };
158
+ };
159
+ classifier: ClassifierConfig;
160
+ scoring: ScoringConfig;
161
+ tiers: Record<Tier, TierConfig>;
162
+ /**
163
+ * Tier configs for agentic mode — models that excel at multi-step tasks.
164
+ * Set to `null` to disable agentic tier selection entirely (forces all
165
+ * requests through `tiers`, even when tools are present in the request).
166
+ */
167
+ agenticTiers?: Record<Tier, TierConfig> | null;
168
+ /** Tier configs for eco profile — ultra cost-optimized (blockrun/eco). `null` falls back to `tiers`. */
169
+ ecoTiers?: Record<Tier, TierConfig> | null;
170
+ /** Tier configs for premium profile — best quality (blockrun/premium). `null` falls back to `tiers`. */
171
+ premiumTiers?: Record<Tier, TierConfig> | null;
172
+ /** Time-windowed promotions that temporarily override tier routing */
173
+ promotions?: Promotion[];
174
+ overrides: OverridesConfig;
175
+ };
176
+
3
177
  /**
4
178
  * Type definitions for BlockRun LLM SDK
5
179
  */
180
+
6
181
  interface FunctionDefinition {
7
182
  name: string;
8
183
  description?: string;
@@ -313,24 +488,21 @@ interface ChatCompletionOptions {
313
488
  fallbackModels?: string[];
314
489
  }
315
490
  type RoutingProfile = "eco" | "auto" | "premium";
316
- type RoutingTier = "SIMPLE" | "MEDIUM" | "COMPLEX" | "REASONING";
317
- interface RoutingDecision {
318
- model: string;
319
- tier: RoutingTier;
320
- confidence: number;
321
- method: "rules" | "llm";
322
- reasoning: string;
323
- costEstimate: number;
324
- baselineCost: number;
325
- savings: number;
326
- /** Routing profile applied by clawrouter (may include "agentic" on gateway responses). */
327
- profile?: RoutingProfile | "agentic";
328
- /** Score used when agentic routing is active. */
329
- agenticScore?: number;
491
+ type RoutingTier = Tier;
492
+ /**
493
+ * Request classification produced by the portfolio router (ClawRouter
494
+ * v0.12.242+, Router v3.4). Present on decisions with `method: "portfolio"`.
495
+ */
496
+ type RoutingTaskType = TaskType;
497
+ /** Primary model + ordered fallbacks for one routing tier. */
498
+ type RoutingTierConfig = RoutingConfig["tiers"][Tier];
499
+ interface RoutingDecision extends RoutingDecision$1 {
330
500
  /**
331
- * Remaining tier models with known pricing, in fallback order. `chat()`
332
- * walks this list when the primary model hits a transient error
333
- * (timeout, network, 5xx). Excludes the primary itself.
501
+ * Remaining gateway-callable models, in the router's ranked order.
502
+ * `chat()` walks this list when the primary model hits a transient error
503
+ * (timeout, network, 429, 5xx). Excludes the primary itself. ClawRouter's
504
+ * proxy-namespace `free/*` ids appear here as their `nvidia/*` gateway
505
+ * ids (or are dropped when the mapping is proxy-only).
334
506
  */
335
507
  fallbacks?: string[];
336
508
  }
@@ -947,6 +1119,16 @@ interface PollOptions {
947
1119
  declare class BlockrunError extends Error {
948
1120
  constructor(message: string);
949
1121
  }
1122
+ /**
1123
+ * Thrown by a helper whose upstream endpoint no longer exists.
1124
+ *
1125
+ * Kept as a throwing method rather than deleted so upgrading does not break
1126
+ * imports or property access — the failure is explicit and immediate instead of
1127
+ * a round trip that returns 410/404.
1128
+ */
1129
+ declare class RetiredEndpointError extends BlockrunError {
1130
+ constructor(message: string);
1131
+ }
950
1132
  declare class PaymentError extends BlockrunError {
951
1133
  constructor(message: string);
952
1134
  }
@@ -1013,8 +1195,11 @@ declare class LLMClient {
1013
1195
  /**
1014
1196
  * Smart chat with automatic model routing.
1015
1197
  *
1016
- * Uses ClawRouter's 14-dimension rule-based scoring algorithm (<1ms, 100% local)
1017
- * to select the cheapest model that can handle your request.
1198
+ * Uses ClawRouter's deterministic portfolio router (Router v3.4, the Auto
1199
+ * default since v0.12.242): it classifies the task shape locally (<1ms, no
1200
+ * extra model call), enforces capability constraints as hard filters, and
1201
+ * ranks an ordered candidate portfolio — the cheapest model that can handle
1202
+ * the request wins, and the rest become the transient-error fallback chain.
1018
1203
  *
1019
1204
  * @param prompt - User message
1020
1205
  * @param options - Optional chat and routing parameters
@@ -1024,7 +1209,8 @@ declare class LLMClient {
1024
1209
  * ```ts
1025
1210
  * const result = await client.smartChat('What is 2+2?');
1026
1211
  * console.log(result.response); // '4'
1027
- * console.log(result.model); // 'google/gemini-2.5-flash-lite'
1212
+ * console.log(result.model); // 'google/gemini-3.5-flash'
1213
+ * console.log(result.routing.method); // 'portfolio'
1028
1214
  * console.log(result.routing.savings); // 0.78 (78% savings)
1029
1215
  * ```
1030
1216
  *
@@ -1284,25 +1470,43 @@ declare class LLMClient {
1284
1470
  * });
1285
1471
  */
1286
1472
  pmQuery(path: string, query: Record<string, unknown>): Promise<Record<string, unknown>>;
1287
- /** List canonical cross-venue markets (Predexon v2). Tier 1 ($0.001/call).
1288
- * Filter with venue, status, category, league, event_id, pagination_key. */
1289
- pmMarkets(params?: Record<string, string>): Promise<Record<string, unknown>>;
1290
- /** List venue-native executable listings flattened across canonical markets
1291
- * (Predexon v2). Tier 1 ($0.001/call). */
1292
- pmListings(params?: Record<string, string>): Promise<Record<string, unknown>>;
1293
- /** Resolve a canonical Predexon outcome ID to its market context and venue
1294
- * listings. Tier 1 ($0.001/call). */
1295
- pmOutcome(predexonId: string): Promise<Record<string, unknown>>;
1473
+ /** RETIRED — `/v1/pm/markets` no longer exists.
1474
+ *
1475
+ * Predexon sunset market matching on 2026-07-20 and the whole canonical layer
1476
+ * went with it, so this path returns 410 upstream. Use
1477
+ * `pm("markets/search", { q })` for cross-venue lookups.
1478
+ *
1479
+ * Kept as a throwing stub rather than deleted so upgrading does not break
1480
+ * property access; it throws before any network I/O.
1481
+ *
1482
+ * @throws {RetiredEndpointError} always. */
1483
+ pmMarkets(_params?: Record<string, string>): Promise<Record<string, unknown>>;
1484
+ /** RETIRED — `/v1/pm/markets/listings` no longer exists (410, sunset
1485
+ * 2026-07-20 with market matching). Use `pm("markets/search", { q })`.
1486
+ *
1487
+ * @throws {RetiredEndpointError} always. */
1488
+ pmListings(_params?: Record<string, string>): Promise<Record<string, unknown>>;
1489
+ /** RETIRED — `/v1/pm/outcomes/{predexonId}` no longer exists (410, sunset
1490
+ * 2026-07-20 with market matching). Use `pm("markets/search", { q })`.
1491
+ *
1492
+ * @throws {RetiredEndpointError} always. */
1493
+ pmOutcome(_predexonId: string): Promise<Record<string, unknown>>;
1296
1494
  /** Polymarket markets with cursor-based keyset pagination (use pagination_key).
1297
1495
  * Tier 1 ($0.001/call). */
1298
1496
  pmPolymarketMarketsKeyset(params?: Record<string, string>): Promise<Record<string, unknown>>;
1299
1497
  /** Polymarket events with cursor-based keyset pagination (use pagination_key).
1300
1498
  * Tier 1 ($0.001/call). */
1301
1499
  pmPolymarketEventsKeyset(params?: Record<string, string>): Promise<Record<string, unknown>>;
1302
- /** List available sports categories. Tier 1 ($0.001/call). */
1500
+ /** List available sports categories. Tier 1 ($0.001/call).
1501
+ *
1502
+ * NOTE: upstream returns 500 for every `sports/*` path as of 2026-08-04.
1503
+ * The route still resolves, so this works again the moment Predexon restores
1504
+ * it, but do not build on it yet. */
1303
1505
  pmSportsCategories(): Promise<Record<string, unknown>>;
1304
1506
  /** List sports markets grouped by game. Filter with league, sport_type,
1305
- * status, venue. Tier 1 ($0.001/call). */
1507
+ * status, venue. Tier 1 ($0.001/call).
1508
+ *
1509
+ * NOTE: upstream returns 500 for every `sports/*` path as of 2026-08-04. */
1306
1510
  pmSportsMarkets(params?: Record<string, string>): Promise<Record<string, unknown>>;
1307
1511
  /** Fetch identity + profile metadata for one wallet (ENS, Twitter, portfolio,
1308
1512
  * etc.). Tier 2 ($0.005/call). */
@@ -3210,4 +3414,4 @@ declare function validateTemperature(temperature?: number): void;
3210
3414
  */
3211
3415
  declare function validateTopP(topP?: number): void;
3212
3416
 
3213
- export { APIError, AnthropicClient, type AudioModel, type AudioTrack, BASE_CHAIN_ID, type BarResolution, type BlockRunAnthropicOptions, BlockrunClient, type BlockrunClientOptions, 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, NETWORK_ALIASES, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PHONE_PRICES, PORTRAIT_ENROLLMENT_PRICE_USD, PaymentError, type PaymentLinks, type PhoneBuyOptions, type PhoneBuyResponse, PhoneClient, type PhoneClientOptions, type PhoneListResponse, type PhoneLookupResponse, type PhoneNumberRecord, type PhoneReleaseResponse, type PhoneRenewResponse, type PollOptions, PortraitClient, type PortraitClientOptions, type PortraitEnrollOptions, type PortraitEnrollResponse, type PriceBar, type PriceCategory, PriceClient, type PriceClientOptions, type PriceHistoryResponse, type PriceOptions, type PricePoint, RPC_PRICE_USD, type ResponseFormat, type RoutingDecision, type RoutingProfile, type RoutingTier, type RpcBatchRequest, RpcClient, type RpcClientOptions, type RpcError, type RpcNetwork, type RpcResponse, type RssSearchSource, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, SUPPORTED_NETWORKS, SearchClient, type SearchClientOptions, type SearchOptions, type SearchParameters, type SearchResult, type SearchSource, type SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type SoundEffectOptions, type SpeechAudio, SpeechClient, type SpeechClientOptions, type SpeechGenerateOptions, type SpeechModel, type SpeechResponse, type SpeechVoice, type Spending, type SpendingReport, type StockMarket, SurfClient, type SurfClientOptions, 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 VoiceInfo, type VoicePreset, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, clearCache, createPaymentPayload, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, extractPaymentDetails, formatFundingMessageCompact, formatNeedsFundingMessage, formatSolanaWalletMigrationNotice, formatWalletCreatedMessage, formatWalletMigrationNotice, getCached, getCachedByRequest, getCostLogSummary, getCostSummary, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, importSolanaWallet, importWallet, listDiscoveredSolanaWallets, listDiscoveredWallets, loadSolanaWallet, loadWallet, logCost, parsePaymentRequired, saveSolanaWallet, saveToCache, saveWallet, scanSolanaWallets, scanWallets, setCache, setupAgentSolanaWallet, setupAgentWallet, solanaClient, solanaKeyToBytes, solanaPublicKey, status, validateMaxTokens, validateModel, validateTemperature, validateTopP };
3417
+ export { APIError, AnthropicClient, type AudioModel, type AudioTrack, BASE_CHAIN_ID, type BarResolution, type BlockRunAnthropicOptions, BlockrunClient, type BlockrunClientOptions, 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, NETWORK_ALIASES, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PHONE_PRICES, PORTRAIT_ENROLLMENT_PRICE_USD, PaymentError, type PaymentLinks, type PhoneBuyOptions, type PhoneBuyResponse, PhoneClient, type PhoneClientOptions, type PhoneListResponse, type PhoneLookupResponse, type PhoneNumberRecord, type PhoneReleaseResponse, type PhoneRenewResponse, type PollOptions, PortraitClient, type PortraitClientOptions, type PortraitEnrollOptions, type PortraitEnrollResponse, type PriceBar, type PriceCategory, PriceClient, type PriceClientOptions, type PriceHistoryResponse, type PriceOptions, type PricePoint, RPC_PRICE_USD, type ResponseFormat, RetiredEndpointError, type RoutingDecision, type RoutingProfile, type RoutingTaskType, type RoutingTier, type RoutingTierConfig, type RpcBatchRequest, RpcClient, type RpcClientOptions, type RpcError, type RpcNetwork, type RpcResponse, type RssSearchSource, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, SUPPORTED_NETWORKS, SearchClient, type SearchClientOptions, type SearchOptions, type SearchParameters, type SearchResult, type SearchSource, type SearchUsage, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type SoundEffectOptions, type SpeechAudio, SpeechClient, type SpeechClientOptions, type SpeechGenerateOptions, type SpeechModel, type SpeechResponse, type SpeechVoice, type Spending, type SpendingReport, type StockMarket, SurfClient, type SurfClientOptions, 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 VoiceInfo, type VoicePreset, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, clearCache, createPaymentPayload, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, extractPaymentDetails, formatFundingMessageCompact, formatNeedsFundingMessage, formatSolanaWalletMigrationNotice, formatWalletCreatedMessage, formatWalletMigrationNotice, getCached, getCachedByRequest, getCostLogSummary, getCostSummary, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, importSolanaWallet, importWallet, listDiscoveredSolanaWallets, listDiscoveredWallets, 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
@@ -8,6 +8,12 @@ var BlockrunError = class extends Error {
8
8
  this.name = "BlockrunError";
9
9
  }
10
10
  };
11
+ var RetiredEndpointError = class extends BlockrunError {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = "RetiredEndpointError";
15
+ }
16
+ };
11
17
  var PaymentError = class extends BlockrunError {
12
18
  constructor(message) {
13
19
  super(message);
@@ -27,6 +33,35 @@ var APIError = class extends BlockrunError {
27
33
 
28
34
  // src/x402.ts
29
35
  import { signTypedData } from "viem/accounts";
36
+
37
+ // src/solana-deps.ts
38
+ var INSTALL_HINT = "npm install @solana/web3.js @solana/spl-token (or pnpm add / yarn add)";
39
+ function missing(pkg, what, cause) {
40
+ return new Error(
41
+ `@blockrun/llm: ${what} requires the optional peer dependency "${pkg}", which is not installed.
42
+
43
+ ${INSTALL_HINT}
44
+
45
+ Solana packages are optional peers so that consumers who only use Base/EVM payments do not inherit them. If you only make Base payments, you should not be reaching this code path \u2014 check which chain you passed.
46
+ Original error: ${cause instanceof Error ? cause.message : String(cause)}`
47
+ );
48
+ }
49
+ async function loadSolanaWeb3(what) {
50
+ try {
51
+ return await import("@solana/web3.js");
52
+ } catch (err) {
53
+ throw missing("@solana/web3.js", what, err);
54
+ }
55
+ }
56
+ async function loadSplToken(what) {
57
+ try {
58
+ return await import("@solana/spl-token");
59
+ } catch (err) {
60
+ throw missing("@solana/spl-token", what, err);
61
+ }
62
+ }
63
+
64
+ // src/x402.ts
30
65
  var BASE_CHAIN_ID = 8453;
31
66
  var USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
32
67
  var SOLANA_NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
@@ -155,9 +190,17 @@ async function createPaymentPayload(privateKey, fromAddress, recipient, amount,
155
190
  return btoa(JSON.stringify(paymentData));
156
191
  }
157
192
  async function createSolanaPaymentPayload(secretKey, fromAddress, recipient, amount, feePayer, options = {}) {
158
- const { Connection, PublicKey, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = await import("@solana/web3.js");
159
- const { getAssociatedTokenAddress, createTransferCheckedInstruction } = await import("@solana/spl-token");
160
- const { Keypair } = await import("@solana/web3.js");
193
+ const {
194
+ Connection,
195
+ PublicKey,
196
+ TransactionMessage,
197
+ VersionedTransaction,
198
+ ComputeBudgetProgram,
199
+ Keypair
200
+ } = await loadSolanaWeb3("createSolanaPaymentPayload()");
201
+ const { getAssociatedTokenAddress, createTransferCheckedInstruction } = await loadSplToken(
202
+ "createSolanaPaymentPayload()"
203
+ );
161
204
  const rpcUrl = options.rpcUrl || "https://sol.blockrun.ai/api/v1/solana/rpc";
162
205
  const connection = options.rpcHeaders ? new Connection(rpcUrl, { httpHeaders: options.rpcHeaders }) : new Connection(rpcUrl);
163
206
  const keypair = Keypair.fromSecretKey(secretKey);
@@ -451,14 +494,14 @@ function getCostSummary() {
451
494
  }
452
495
 
453
496
  // src/version.ts
454
- var SDK_VERSION = "3.9.0";
497
+ var SDK_VERSION = "3.11.0";
455
498
  var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
456
499
 
457
500
  // src/client.ts
458
501
  function isTransientError(err) {
459
502
  if (err instanceof PaymentError) return false;
460
503
  if (err instanceof APIError) {
461
- return [502, 503, 504, 522, 524].includes(err.statusCode);
504
+ return [429, 502, 503, 504, 522, 524].includes(err.statusCode);
462
505
  }
463
506
  if (err instanceof Error) {
464
507
  if (err.name === "AbortError") return true;
@@ -585,8 +628,11 @@ var LLMClient = class _LLMClient {
585
628
  /**
586
629
  * Smart chat with automatic model routing.
587
630
  *
588
- * Uses ClawRouter's 14-dimension rule-based scoring algorithm (<1ms, 100% local)
589
- * to select the cheapest model that can handle your request.
631
+ * Uses ClawRouter's deterministic portfolio router (Router v3.4, the Auto
632
+ * default since v0.12.242): it classifies the task shape locally (<1ms, no
633
+ * extra model call), enforces capability constraints as hard filters, and
634
+ * ranks an ordered candidate portfolio — the cheapest model that can handle
635
+ * the request wins, and the rest become the transient-error fallback chain.
590
636
  *
591
637
  * @param prompt - User message
592
638
  * @param options - Optional chat and routing parameters
@@ -596,7 +642,8 @@ var LLMClient = class _LLMClient {
596
642
  * ```ts
597
643
  * const result = await client.smartChat('What is 2+2?');
598
644
  * console.log(result.response); // '4'
599
- * console.log(result.model); // 'google/gemini-2.5-flash-lite'
645
+ * console.log(result.model); // 'google/gemini-3.5-flash'
646
+ * console.log(result.routing.method); // 'portfolio'
600
647
  * console.log(result.routing.savings); // 0.78 (78% savings)
601
648
  * ```
602
649
  *
@@ -628,11 +675,15 @@ var LLMClient = class _LLMClient {
628
675
  routingProfile: options?.routingProfile
629
676
  });
630
677
  const tierConfigs = decision.tierConfigs ?? DEFAULT_ROUTING_CONFIG.tiers;
631
- const fullChain = getFallbackChain(decision.tier, tierConfigs);
632
- const fallbacks = fullChain.filter(
633
- (id) => id !== decision.model && modelPricing.has(id)
634
- );
635
- const response = await this.chat(decision.model, prompt, {
678
+ const ranked = decision.candidates?.length ? decision.candidates : [decision.model, ...getFallbackChain(decision.tier, tierConfigs)];
679
+ const callable = [];
680
+ for (const id of ranked) {
681
+ const resolved = !id.startsWith("free/") ? id : modelPricing.has(`nvidia/${id.slice(5)}`) ? `nvidia/${id.slice(5)}` : null;
682
+ if (resolved && !callable.includes(resolved)) callable.push(resolved);
683
+ }
684
+ const primary = callable[0] ?? decision.model;
685
+ const fallbacks = callable.slice(1);
686
+ const response = await this.chat(primary, prompt, {
636
687
  system: options?.system,
637
688
  maxTokens: options?.maxTokens,
638
689
  temperature: options?.temperature,
@@ -645,8 +696,8 @@ var LLMClient = class _LLMClient {
645
696
  });
646
697
  return {
647
698
  response,
648
- model: decision.model,
649
- routing: { ...decision, fallbacks }
699
+ model: primary,
700
+ routing: { ...decision, model: primary, fallbacks }
650
701
  };
651
702
  }
652
703
  /**
@@ -1670,20 +1721,38 @@ var LLMClient = class _LLMClient {
1670
1721
  }
1671
1722
  // ── PM convenience helpers (Predexon v2) ─────────────────────────────────
1672
1723
  // Thin wrappers over pm() / pmQuery() for the most common v2 endpoints.
1673
- /** List canonical cross-venue markets (Predexon v2). Tier 1 ($0.001/call).
1674
- * Filter with venue, status, category, league, event_id, pagination_key. */
1675
- async pmMarkets(params) {
1676
- return this.pm("markets", params);
1724
+ /** RETIRED — `/v1/pm/markets` no longer exists.
1725
+ *
1726
+ * Predexon sunset market matching on 2026-07-20 and the whole canonical layer
1727
+ * went with it, so this path returns 410 upstream. Use
1728
+ * `pm("markets/search", { q })` for cross-venue lookups.
1729
+ *
1730
+ * Kept as a throwing stub rather than deleted so upgrading does not break
1731
+ * property access; it throws before any network I/O.
1732
+ *
1733
+ * @throws {RetiredEndpointError} always. */
1734
+ async pmMarkets(_params) {
1735
+ throw new RetiredEndpointError(
1736
+ '/v1/pm/markets was sunset by Predexon on 2026-07-20 (upstream 410). Use pm("markets/search", { q }) for cross-venue lookups.'
1737
+ );
1677
1738
  }
1678
- /** List venue-native executable listings flattened across canonical markets
1679
- * (Predexon v2). Tier 1 ($0.001/call). */
1680
- async pmListings(params) {
1681
- return this.pm("markets/listings", params);
1739
+ /** RETIRED — `/v1/pm/markets/listings` no longer exists (410, sunset
1740
+ * 2026-07-20 with market matching). Use `pm("markets/search", { q })`.
1741
+ *
1742
+ * @throws {RetiredEndpointError} always. */
1743
+ async pmListings(_params) {
1744
+ throw new RetiredEndpointError(
1745
+ '/v1/pm/markets/listings was sunset by Predexon on 2026-07-20 (upstream 410). Use pm("markets/search", { q }) for cross-venue lookups.'
1746
+ );
1682
1747
  }
1683
- /** Resolve a canonical Predexon outcome ID to its market context and venue
1684
- * listings. Tier 1 ($0.001/call). */
1685
- async pmOutcome(predexonId) {
1686
- return this.pm(`outcomes/${predexonId}`);
1748
+ /** RETIRED — `/v1/pm/outcomes/{predexonId}` no longer exists (410, sunset
1749
+ * 2026-07-20 with market matching). Use `pm("markets/search", { q })`.
1750
+ *
1751
+ * @throws {RetiredEndpointError} always. */
1752
+ async pmOutcome(_predexonId) {
1753
+ throw new RetiredEndpointError(
1754
+ '/v1/pm/outcomes/{predexon_id} was sunset by Predexon on 2026-07-20 (upstream 410). Use pm("markets/search", { q }) for cross-venue lookups.'
1755
+ );
1687
1756
  }
1688
1757
  /** Polymarket markets with cursor-based keyset pagination (use pagination_key).
1689
1758
  * Tier 1 ($0.001/call). */
@@ -1695,12 +1764,18 @@ var LLMClient = class _LLMClient {
1695
1764
  async pmPolymarketEventsKeyset(params) {
1696
1765
  return this.pm("polymarket/events/keyset", params);
1697
1766
  }
1698
- /** List available sports categories. Tier 1 ($0.001/call). */
1767
+ /** List available sports categories. Tier 1 ($0.001/call).
1768
+ *
1769
+ * NOTE: upstream returns 500 for every `sports/*` path as of 2026-08-04.
1770
+ * The route still resolves, so this works again the moment Predexon restores
1771
+ * it, but do not build on it yet. */
1699
1772
  async pmSportsCategories() {
1700
1773
  return this.pm("sports/categories");
1701
1774
  }
1702
1775
  /** List sports markets grouped by game. Filter with league, sport_type,
1703
- * status, venue. Tier 1 ($0.001/call). */
1776
+ * status, venue. Tier 1 ($0.001/call).
1777
+ *
1778
+ * NOTE: upstream returns 500 for every `sports/*` path as of 2026-08-04. */
1704
1779
  async pmSportsMarkets(params) {
1705
1780
  return this.pm("sports/markets", params);
1706
1781
  }
@@ -4781,7 +4856,7 @@ import * as os3 from "os";
4781
4856
  var WALLET_DIR2 = path3.join(os3.homedir(), ".blockrun");
4782
4857
  var SOLANA_WALLET_FILE = path3.join(WALLET_DIR2, ".solana-session");
4783
4858
  async function createSolanaWallet() {
4784
- const { Keypair } = await import("@solana/web3.js");
4859
+ const { Keypair } = await loadSolanaWeb3("Solana wallet operations");
4785
4860
  const bs58 = await import("bs58");
4786
4861
  const keypair = Keypair.generate();
4787
4862
  return {
@@ -4838,7 +4913,7 @@ async function solanaKeyToBytes(privateKey) {
4838
4913
  }
4839
4914
  }
4840
4915
  async function solanaPublicKey(privateKey) {
4841
- const { Keypair } = await import("@solana/web3.js");
4916
+ const { Keypair } = await loadSolanaWeb3("Solana wallet operations");
4842
4917
  const bytes = await solanaKeyToBytes(privateKey);
4843
4918
  return Keypair.fromSecretKey(bytes).publicKey.toBase58();
4844
4919
  }
@@ -6131,6 +6206,7 @@ export {
6131
6206
  PortraitClient,
6132
6207
  PriceClient,
6133
6208
  RPC_PRICE_USD,
6209
+ RetiredEndpointError,
6134
6210
  RpcClient,
6135
6211
  SOLANA_NETWORK,
6136
6212
  SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/llm",
3
- "version": "3.9.0",
3
+ "version": "3.11.0",
4
4
  "type": "module",
5
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",
@@ -18,8 +18,8 @@
18
18
  "README.md"
19
19
  ],
20
20
  "scripts": {
21
- "build": "tsup src/index.ts --format cjs,esm --dts --clean --external @blockrun/clawrouter --external @anthropic-ai/sdk --external @solana/web3.js --external @solana/spl-token --external bs58",
22
- "dev": "tsup src/index.ts --format cjs,esm --dts --watch --external @blockrun/clawrouter --external @anthropic-ai/sdk --external @solana/web3.js --external @solana/spl-token --external bs58",
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
23
  "test": "vitest",
24
24
  "lint": "eslint src/",
25
25
  "typecheck": "tsc --noEmit"
@@ -52,11 +52,11 @@
52
52
  "viem": "^2.49.0"
53
53
  },
54
54
  "optionalDependencies": {
55
- "@anthropic-ai/sdk": "^0.39.0",
56
- "@solana/spl-token": "^0.4.14",
57
- "@solana/web3.js": "^1.98.4"
55
+ "@anthropic-ai/sdk": "^0.39.0"
58
56
  },
59
57
  "devDependencies": {
58
+ "@blockrun/clawrouter": "^0.12.244",
59
+ "@blockrun/router-core": "https://codeload.github.com/BlockRunAI/router-core/tar.gz/6a790ebec60161825bbc8c4093fd221006b4e5fb",
60
60
  "@eslint/js": "^9.39.4",
61
61
  "@types/node": "^20.19.41",
62
62
  "eslint": "^9.39.4",
@@ -77,11 +77,19 @@
77
77
  },
78
78
  "packageManager": "pnpm@9.15.4",
79
79
  "peerDependencies": {
80
- "@blockrun/clawrouter": "^0.12.222"
80
+ "@blockrun/clawrouter": "^0.12.242",
81
+ "@solana/spl-token": "^0.4.14",
82
+ "@solana/web3.js": "^1.98.4"
81
83
  },
82
84
  "peerDependenciesMeta": {
83
85
  "@blockrun/clawrouter": {
84
86
  "optional": true
87
+ },
88
+ "@solana/spl-token": {
89
+ "optional": true
90
+ },
91
+ "@solana/web3.js": {
92
+ "optional": true
85
93
  }
86
94
  }
87
95
  }