@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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @blockrun/llm (TypeScript SDK)
2
2
 
3
- > **@blockrun/llm** is a TypeScript/Node.js SDK for accessing <!-- br:models.chatVisible -->66<!-- /br:models.chatVisible --> large language models (GPT-5, Claude, Gemini, Grok, DeepSeek, Kimi, and more) with automatic pay-per-request USDC micropayments via the x402 protocol. No API keys required — your wallet signature is your authentication. Supports **streaming**, smart routing, Base and Solana chains.
3
+ > **@blockrun/llm** is a TypeScript/Node.js SDK for accessing <!-- br:models.chatVisible -->71<!-- /br:models.chatVisible --> large language models (GPT-5, Claude, Gemini, Grok, DeepSeek, Kimi, and more) with automatic pay-per-request USDC micropayments via the x402 protocol. No API keys required — your wallet signature is your authentication. Supports **streaming**, smart routing, Base and Solana chains.
4
4
  >
5
5
  > 🆓 **Includes 7 fully-free NVIDIA-hosted models** (5 visible in `/v1/models`, 2 hidden but directly callable) — DeepSeek V4 Flash (1M context), Nemotron Nano Omni (vision), Qwen3 Coder, Llama 4, Mistral, plus the gpt-oss pair. Zero USDC, no rate-limit gimmicks. Use `routingProfile: 'free'` or call any `nvidia/*` model directly.
6
6
 
@@ -21,7 +21,7 @@
21
21
  ## Installation
22
22
 
23
23
  ```bash
24
- # Base and Solana support (optional Solana deps auto-installed)
24
+ # Base / EVM payments — nothing else needed
25
25
  npm install @blockrun/llm
26
26
  # or
27
27
  pnpm add @blockrun/llm
@@ -29,6 +29,21 @@ pnpm add @blockrun/llm
29
29
  yarn add @blockrun/llm
30
30
  ```
31
31
 
32
+ **Solana payments** need two more packages. They are optional peer dependencies,
33
+ so npm will not install them for you:
34
+
35
+ ```bash
36
+ npm install @blockrun/llm @solana/web3.js @solana/spl-token
37
+ ```
38
+
39
+ Why they are not automatic: `@solana/spl-token` pulls in `bigint-buffer`, whose
40
+ native `toBigIntLE()` has an unpatched buffer overflow
41
+ ([GHSA-3gc7-fjrx-p6mg](https://github.com/advisories/GHSA-3gc7-fjrx-p6mg)) with no
42
+ fixed release anywhere. As an optional *dependency* it landed in the lockfile of
43
+ every consumer, including projects that only ever pay on Base. As an optional
44
+ *peer* it reaches only the projects that ask for Solana. Calling a Solana path
45
+ without them throws an error naming the exact install command.
46
+
32
47
  ## Quick Start (Base - Default)
33
48
 
34
49
  ```typescript
@@ -221,7 +236,24 @@ Every paid request is a real on-chain USDC transfer — look up your wallet addr
221
236
 
222
237
  ## Smart Routing (ClawRouter)
223
238
 
224
- Let the SDK automatically pick the cheapest capable model for each request:
239
+ Let the SDK automatically pick the cheapest capable model for each request — **<!-- br:savings.autoVsBaselinePct -->88<!-- /br:savings.autoVsBaselinePct -->% cheaper than pinning Claude Opus 5** for the same traffic on `auto`, **<!-- br:savings.ecoVsBaselinePct -->98<!-- /br:savings.ecoVsBaselinePct -->%** on `eco`.
240
+
241
+ Not an "up to" figure. The baseline, the workload mix and the token ratio are
242
+ published in [`savings-mix.json`](https://github.com/BlockRunAI/blockrun/blob/main/src/brand/savings-mix.json),
243
+ priced against the live catalog, so anyone can recompute the claim and get the
244
+ same answer.
245
+
246
+ Smart routing is powered by [ClawRouter](https://github.com/BlockRunAI/ClawRouter) —
247
+ the open-source, agent-first LLM router: wallet signatures instead of API keys,
248
+ USDC micropayments instead of credit cards, and <1ms fully-local routing with
249
+ zero external calls. In this SDK it is an **optional peer dependency** —
250
+ install it alongside the SDK:
251
+
252
+ ```bash
253
+ npm install @blockrun/clawrouter
254
+ ```
255
+
256
+ Only `smartChat()` needs it: every other API works without it, and the package is loaded lazily, so a missing or broken router can never break `import '@blockrun/llm'`. Calling `smartChat()` without it throws an error naming the package instead of a cryptic module-load failure.
225
257
 
226
258
  ```typescript
227
259
  import { LLMClient } from '@blockrun/llm';
@@ -232,23 +264,28 @@ const client = new LLMClient();
232
264
  const result = await client.smartChat('What is 2+2?');
233
265
  console.log(result.response); // '4'
234
266
  console.log(result.model); // 'moonshot/kimi-k2.5' (cheap, fast)
235
- console.log(`Saved ${(result.routing.savings * 100).toFixed(0)}%`); // 'Saved 87%'
267
+ console.log(`Saved ${(result.routing.savings * 100).toFixed(0)}%`); // 'Saved 88%'
236
268
 
237
269
  // Complex reasoning task -> routes to reasoning model
238
270
  const complex = await client.smartChat('Prove the Riemann hypothesis step by step');
239
271
  console.log(complex.model); // 'xai/grok-4-1-fast-reasoning'
240
272
 
273
+ // Inspect how the request was classified and ranked (Router v3.4 portfolio).
274
+ console.log(complex.routing.method); // 'portfolio'
275
+ console.log(complex.routing.taskType); // 'reasoning'
276
+ console.log(complex.routing.candidates); // ranked, capability-eligible models
277
+
241
278
  // Inspect the fallback chain SmartChat will walk on transient errors.
242
279
  console.log(complex.routing.fallbacks); // ['anthropic/claude-opus-4.7', ...]
243
280
  ```
244
281
 
245
282
  ### Automatic Fallback on Transient Errors
246
283
 
247
- `smartChat()` populates a tier-specific fallback chain and `chat()` /
248
- `chatCompletion()` walk it automatically when the primary model returns a
249
- transient error — timeouts, network failures, or 5xx responses (502/503/504/
250
- 522/524). 4xx errors and `PaymentError` propagate immediately so wallet /
251
- auth issues surface fast.
284
+ `smartChat()` populates a fallback chain from the portfolio ranking and
285
+ `chat()` / `chatCompletion()` walk it automatically when the primary model
286
+ returns a transient error — timeouts, network failures, 429 rate limits, or
287
+ 5xx responses (502/503/504/522/524). Other 4xx errors and `PaymentError`
288
+ propagate immediately so wallet / auth issues surface fast.
252
289
 
253
290
  ```typescript
254
291
  // Manually pass a fallback chain to chat() / chatCompletion()
@@ -261,12 +298,12 @@ const reply = await client.chat('nvidia/deepseek-v4-flash', 'hello', {
261
298
 
262
299
  ### Routing Profiles
263
300
 
264
- | Profile | Description | Best For |
265
- |---------|-------------|----------|
266
- | `free` | NVIDIA free tier — smart-routes across <!-- br:models.free -->8<!-- /br:models.free --> models (DeepSeek V4 Flash, Nemotron Nano Omni, Qwen3, Llama 4, Mistral, plus 2 hidden gpt-oss) | Zero-cost testing, dev, prod |
267
- | `eco` | Cheapest models per tier (DeepSeek, xAI) | Cost-sensitive production |
268
- | `auto` | Best balance of cost/quality (default) | General use |
269
- | `premium` | Top-tier models (OpenAI, Anthropic) | Quality-critical tasks |
301
+ | Profile | Strategy | Savings vs Opus 5 | Best For |
302
+ |---------|----------|-------------------|----------|
303
+ | `free` | NVIDIA free tier — smart-routes across <!-- br:models.free -->6<!-- /br:models.free --> models (DeepSeek V4 Flash, Nemotron Nano Omni, Qwen3, Llama 4, Mistral, plus 2 hidden gpt-oss) | **100%** | Zero-cost testing, dev, prod |
304
+ | `eco` | Cheapest capable model per tier | **<!-- br:savings.ecoVsBaselinePct -->98<!-- /br:savings.ecoVsBaselinePct -->%** | Cost-sensitive production |
305
+ | `auto` | Best balance of cost/quality (default) | **<!-- br:savings.autoVsBaselinePct -->88<!-- /br:savings.autoVsBaselinePct -->%** | General use |
306
+ | `premium` | Top-tier models (OpenAI, Anthropic) | 0% | Quality-critical tasks |
270
307
 
271
308
  ```typescript
272
309
  // Use premium models for complex tasks
@@ -279,23 +316,78 @@ console.log(result.model); // 'anthropic/claude-opus-4.7'
279
316
 
280
317
  ### How ClawRouter Works
281
318
 
282
- ClawRouter uses a 14-dimension rule-based classifier to analyze each request:
283
-
284
- - **Token count** - Short vs long prompts
285
- - **Code presence** - Programming keywords
286
- - **Reasoning markers** - "prove", "step by step", etc.
287
- - **Technical terms** - Architecture, optimization, etc.
288
- - **Creative markers** - Story, poem, brainstorm, etc.
289
- - **Agentic patterns** - Multi-step, tool use indicators
290
-
291
- The classifier runs in <1ms, 100% locally, and routes to one of four tiers:
292
-
293
- | Tier | Example Tasks | Auto Profile Model |
294
- |------|---------------|-------------------|
295
- | SIMPLE | "What is 2+2?", definitions | moonshot/kimi-k2.5 |
296
- | MEDIUM | Code snippets, explanations | xai/grok-code-fast-1 |
297
- | COMPLEX | Architecture, long documents | google/gemini-3.1-pro |
298
- | REASONING | Proofs, multi-step reasoning | xai/grok-4-1-fast-reasoning |
319
+ Since ClawRouter v0.12.242, Auto uses the deterministic **Router v3.4 portfolio
320
+ strategy**: it classifies the task shape locally across
321
+ <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions
322
+ (token count, code presence, reasoning markers, technical/creative terms,
323
+ agentic patterns, …), enforces tool / vision / structured-output / context
324
+ constraints as **hard filters**, then ranks an ordered candidate portfolio.
325
+ The winner becomes `routing.model`; the rest surface as `routing.candidates`
326
+ and feed SmartChat's transient-error fallback chain. Routing stays 100% local
327
+ and deterministic — <1ms, no extra model call, no network hop.
328
+
329
+ Classification still maps to one of four tiers (`routing.tier`). Each
330
+ tier × profile has a designated primary (what the rules strategy —
331
+ `routing.method: 'rules'`, the rollback lever — routes to directly, and what
332
+ anchors the portfolio's candidate pool):
333
+
334
+ | Tier | Example Tasks | ECO | AUTO | PREMIUM |
335
+ |------|---------------|-----|------|---------|
336
+ | SIMPLE | "What is 2+2?", definitions | free/gpt-oss-120b † (**FREE**) | gemini-2.5-flash ($0.30/$2.50) | kimi-k2.7 † ($0.95/$4.00) |
337
+ | MEDIUM | Code snippets, explanations | gemini-3.1-flash-lite ($0.25/$1.50) | kimi-k2.7 ($0.95/$4.00) | gpt-5.3-codex ($1.75/$14.00) |
338
+ | COMPLEX | Architecture, long documents | gemini-3.1-flash-lite ($0.25/$1.50) | gemini-3.1-pro ($2/$12) | claude-fable-5 ($10/$50) |
339
+ | REASONING | Proofs, multi-step reasoning | grok-4-1-fast-reasoning † ($0.20/$0.50) | grok-4-1-fast-reasoning † ($0.20/$0.50) | claude-sonnet-4.6 ($3/$15) |
340
+
341
+ † Withheld from `/v1/models` — the router still calls it by direct ID, but you
342
+ will not find it on the public pricing page. The published savings claim is
343
+ priced on visible models only.
344
+
345
+ This table mirrors ClawRouter's tier configs at the version this SDK pins;
346
+ the [ClawRouter README](https://github.com/BlockRunAI/ClawRouter#how-it-works)
347
+ is the live source of truth as models and prices move.
348
+
349
+ ### Routing Metadata Reference
350
+
351
+ Every `smartChat()` result carries the full decision on `result.routing`
352
+ (type `RoutingDecision`) — enough to log, audit, or replay why a model was
353
+ picked:
354
+
355
+ | Field | Description |
356
+ |-------|-------------|
357
+ | `model` | Selected model id (same as `result.model`) |
358
+ | `method` | `'portfolio'` (the Auto default), `'rules'` (rollback strategy), or `'llm'` |
359
+ | `tier` | Task tier: `'SIMPLE'`, `'MEDIUM'`, `'COMPLEX'`, or `'REASONING'` |
360
+ | `taskType` | Portfolio task classification: `'chat'`, `'extraction'`, `'code_edit'`, `'code_agent'`, `'tool_agent'`, `'debug'`, `'reasoning'`, `'reasoning_math'`, `'long_context'`, `'vision'`, … |
361
+ | `candidates` | Ordered, capability-eligible models ranked by the portfolio router; the first entry is `model` |
362
+ | `candidateScores` | Per-candidate score breakdown (`quality` / `cost` / `speed` / `reliability`), ordered with `candidates` |
363
+ | `fallbacks` | The chain `chat()` walks on transient errors (timeout / network / 429 / 5xx) — `candidates` minus the primary, with ClawRouter's proxy-namespace `free/*` ids mapped to their `nvidia/*` gateway ids (SDK-computed) |
364
+ | `savings` | 0–1 fraction saved vs the premium baseline |
365
+ | `costEstimate` / `baselineCost` | Estimated cost of the pick vs that baseline, in USD |
366
+ | `confidence` | Sigmoid-calibrated classifier confidence, 0–1 |
367
+ | `routerVersion` | `'v3-portfolio'` or `'v2-rules'` |
368
+ | `profile` | Routing profile applied: `'auto'`, `'eco'`, `'premium'`, or `'agentic'` |
369
+ | `reasoning` | Human-readable explanation of the decision |
370
+ | `tierConfigs` | The tier → primary/fallback map the decision was made against |
371
+
372
+ ### TypeScript Types
373
+
374
+ `RoutingDecision`, `RoutingProfile`, `RoutingTier`, `RoutingTaskType`, and
375
+ `RoutingTierConfig` are exported from `@blockrun/llm`. They are derived from
376
+ [`@blockrun/router-core`](https://github.com/BlockRunAI/router-core) — the
377
+ routing engine ClawRouter bundles — pinned to the exact commit ClawRouter's
378
+ published build inlines, and shipped **inlined in this SDK's declaration
379
+ files**. You do not need to install `@blockrun/clawrouter` (or router-core,
380
+ which is not on npm) for your project to typecheck against these types; the
381
+ runtime package is only needed to actually call `smartChat()`.
382
+
383
+ ### Going Deeper
384
+
385
+ - [ClawRouter](https://github.com/BlockRunAI/ClawRouter) — the router itself: OpenClaw plugin, standalone proxy for Cursor / continue.dev / any OpenAI-compatible client, Telegram integration
386
+ - [Routing profiles in depth](https://github.com/BlockRunAI/ClawRouter/blob/main/docs/routing-profiles.md) — ECO / AUTO / PREMIUM details
387
+ - [How the routing engine works](https://github.com/BlockRunAI/ClawRouter/blob/main/docs/smart-llm-router-14-dimension-classifier.md) — the classifier, dimension by dimension
388
+ - [Router benchmark](https://github.com/BlockRunAI/ClawRouter/blob/main/docs/llm-router-benchmark-46-models-sub-1ms-routing.md) — sub-1ms routing across the catalog
389
+ - [ClawRouter vs OpenRouter](https://github.com/BlockRunAI/ClawRouter/blob/main/docs/clawrouter-vs-openrouter-llm-routing-comparison.md) — head-to-head comparison
390
+ - [`@blockrun/router-core`](https://github.com/BlockRunAI/router-core) — the deterministic routing engine both share
299
391
 
300
392
  ## Available Models
301
393
 
@@ -858,7 +950,7 @@ const response2 = await client.chat('anthropic/claude-sonnet-4', 'Write a haiku'
858
950
 
859
951
  ### Smart Routing (ClawRouter)
860
952
 
861
- Save up to <!-- br:savings.autoVsBaselinePct -->87<!-- /br:savings.autoVsBaselinePct -->% on inference costs with intelligent model routing. ClawRouter uses a <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions -->-dimension rule-based scoring algorithm to select the cheapest model that can handle your request (<1ms, 100% local).
953
+ Save up to <!-- br:savings.autoVsBaselinePct -->88<!-- /br:savings.autoVsBaselinePct -->% on inference costs with intelligent model routing. ClawRouter's deterministic portfolio router (v3.4, default since ClawRouter v0.12.242) classifies each request across <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions, applies hard capability filters, and ranks the cheapest capable models (<1ms, 100% local). Requires the optional peer dependency: `npm install @blockrun/clawrouter`.
862
954
 
863
955
  ```typescript
864
956
  import { LLMClient } from '@blockrun/llm';
@@ -870,7 +962,7 @@ const result = await client.smartChat('What is 2+2?');
870
962
  console.log(result.response); // '4'
871
963
  console.log(result.model); // 'google/gemini-2.5-flash'
872
964
  console.log(result.routing.tier); // 'SIMPLE'
873
- console.log(`Saved ${(result.routing.savings * 100).toFixed(0)}%`); // 'Saved 87%'
965
+ console.log(`Saved ${(result.routing.savings * 100).toFixed(0)}%`); // 'Saved 88%'
874
966
 
875
967
  // Routing profiles
876
968
  const free = await client.smartChat('Hello!', { routingProfile: 'free' }); // Zero cost
@@ -883,7 +975,7 @@ const premium = await client.smartChat('Write a legal brief', { routingProfile:
883
975
 
884
976
  | Profile | Description | Best For |
885
977
  |---------|-------------|----------|
886
- | `free` | NVIDIA free tier (<!-- br:models.free -->8<!-- /br:models.free --> models, smart-routed) | Zero-cost testing, dev, prod |
978
+ | `free` | NVIDIA free tier (<!-- br:models.free -->6<!-- /br:models.free --> models, smart-routed) | Zero-cost testing, dev, prod |
887
979
  | `eco` | Budget-optimized | Cost-sensitive workloads |
888
980
  | `auto` | Intelligent routing (default) | General use |
889
981
  | `premium` | Best quality models | Critical tasks |
@@ -1427,7 +1519,7 @@ The `AnthropicClient` wraps the official `@anthropic-ai/sdk` with a custom fetch
1427
1519
  When you make an API call, the SDK automatically handles x402 payment. It signs a USDC transaction locally using your wallet private key (which never leaves your machine), and includes the payment proof in the request header. Settlement is non-custodial and instant on Base or Solana.
1428
1520
 
1429
1521
  ### What is smart routing / ClawRouter?
1430
- ClawRouter is a built-in smart routing engine that analyzes your request across <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions and automatically picks the cheapest model capable of handling it. Routing happens locally in under 1ms. It can save up to <!-- br:savings.autoVsBaselinePct -->87<!-- /br:savings.autoVsBaselinePct -->% on LLM costs compared to using premium models for every request.
1522
+ ClawRouter is the SDK's smart routing engine, shipped as the optional `@blockrun/clawrouter` peer dependency (`npm install @blockrun/clawrouter` — only `smartChat()` needs it). It analyzes your request across <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions and automatically picks the cheapest model capable of handling it. Routing happens locally in under 1ms. It can save up to <!-- br:savings.autoVsBaselinePct -->88<!-- /br:savings.autoVsBaselinePct -->% on LLM costs compared to using premium models for every request.
1431
1523
 
1432
1524
  ### Does it support streaming?
1433
1525
  Yes — as of v1.6.1. Use `client.chatCompletionStream()` for native streaming or `stream: true` in the OpenAI-compatible client. Payment is handled automatically: the SDK signs USDC payment before streaming begins, and caches payment requirements per model so subsequent calls skip the 402 round-trip (~200ms faster).
package/dist/index.cjs CHANGED
@@ -48,6 +48,7 @@ __export(index_exports, {
48
48
  PortraitClient: () => PortraitClient,
49
49
  PriceClient: () => PriceClient,
50
50
  RPC_PRICE_USD: () => RPC_PRICE_USD,
51
+ RetiredEndpointError: () => RetiredEndpointError,
51
52
  RpcClient: () => RpcClient,
52
53
  SOLANA_NETWORK: () => SOLANA_NETWORK,
53
54
  SOLANA_WALLET_FILE_PATH: () => SOLANA_WALLET_FILE,
@@ -121,6 +122,12 @@ var BlockrunError = class extends Error {
121
122
  this.name = "BlockrunError";
122
123
  }
123
124
  };
125
+ var RetiredEndpointError = class extends BlockrunError {
126
+ constructor(message) {
127
+ super(message);
128
+ this.name = "RetiredEndpointError";
129
+ }
130
+ };
124
131
  var PaymentError = class extends BlockrunError {
125
132
  constructor(message) {
126
133
  super(message);
@@ -140,6 +147,35 @@ var APIError = class extends BlockrunError {
140
147
 
141
148
  // src/x402.ts
142
149
  var import_accounts = require("viem/accounts");
150
+
151
+ // src/solana-deps.ts
152
+ var INSTALL_HINT = "npm install @solana/web3.js @solana/spl-token (or pnpm add / yarn add)";
153
+ function missing(pkg, what, cause) {
154
+ return new Error(
155
+ `@blockrun/llm: ${what} requires the optional peer dependency "${pkg}", which is not installed.
156
+
157
+ ${INSTALL_HINT}
158
+
159
+ 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.
160
+ Original error: ${cause instanceof Error ? cause.message : String(cause)}`
161
+ );
162
+ }
163
+ async function loadSolanaWeb3(what) {
164
+ try {
165
+ return await import("@solana/web3.js");
166
+ } catch (err) {
167
+ throw missing("@solana/web3.js", what, err);
168
+ }
169
+ }
170
+ async function loadSplToken(what) {
171
+ try {
172
+ return await import("@solana/spl-token");
173
+ } catch (err) {
174
+ throw missing("@solana/spl-token", what, err);
175
+ }
176
+ }
177
+
178
+ // src/x402.ts
143
179
  var BASE_CHAIN_ID = 8453;
144
180
  var USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
145
181
  var SOLANA_NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
@@ -268,9 +304,17 @@ async function createPaymentPayload(privateKey, fromAddress, recipient, amount,
268
304
  return btoa(JSON.stringify(paymentData));
269
305
  }
270
306
  async function createSolanaPaymentPayload(secretKey, fromAddress, recipient, amount, feePayer, options = {}) {
271
- const { Connection, PublicKey, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = await import("@solana/web3.js");
272
- const { getAssociatedTokenAddress, createTransferCheckedInstruction } = await import("@solana/spl-token");
273
- const { Keypair } = await import("@solana/web3.js");
307
+ const {
308
+ Connection,
309
+ PublicKey,
310
+ TransactionMessage,
311
+ VersionedTransaction,
312
+ ComputeBudgetProgram,
313
+ Keypair
314
+ } = await loadSolanaWeb3("createSolanaPaymentPayload()");
315
+ const { getAssociatedTokenAddress, createTransferCheckedInstruction } = await loadSplToken(
316
+ "createSolanaPaymentPayload()"
317
+ );
274
318
  const rpcUrl = options.rpcUrl || "https://sol.blockrun.ai/api/v1/solana/rpc";
275
319
  const connection = options.rpcHeaders ? new Connection(rpcUrl, { httpHeaders: options.rpcHeaders }) : new Connection(rpcUrl);
276
320
  const keypair = Keypair.fromSecretKey(secretKey);
@@ -564,14 +608,14 @@ function getCostSummary() {
564
608
  }
565
609
 
566
610
  // src/version.ts
567
- var SDK_VERSION = "3.9.0";
611
+ var SDK_VERSION = "3.11.0";
568
612
  var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
569
613
 
570
614
  // src/client.ts
571
615
  function isTransientError(err) {
572
616
  if (err instanceof PaymentError) return false;
573
617
  if (err instanceof APIError) {
574
- return [502, 503, 504, 522, 524].includes(err.statusCode);
618
+ return [429, 502, 503, 504, 522, 524].includes(err.statusCode);
575
619
  }
576
620
  if (err instanceof Error) {
577
621
  if (err.name === "AbortError") return true;
@@ -698,8 +742,11 @@ var LLMClient = class _LLMClient {
698
742
  /**
699
743
  * Smart chat with automatic model routing.
700
744
  *
701
- * Uses ClawRouter's 14-dimension rule-based scoring algorithm (<1ms, 100% local)
702
- * to select the cheapest model that can handle your request.
745
+ * Uses ClawRouter's deterministic portfolio router (Router v3.4, the Auto
746
+ * default since v0.12.242): it classifies the task shape locally (<1ms, no
747
+ * extra model call), enforces capability constraints as hard filters, and
748
+ * ranks an ordered candidate portfolio — the cheapest model that can handle
749
+ * the request wins, and the rest become the transient-error fallback chain.
703
750
  *
704
751
  * @param prompt - User message
705
752
  * @param options - Optional chat and routing parameters
@@ -709,7 +756,8 @@ var LLMClient = class _LLMClient {
709
756
  * ```ts
710
757
  * const result = await client.smartChat('What is 2+2?');
711
758
  * console.log(result.response); // '4'
712
- * console.log(result.model); // 'google/gemini-2.5-flash-lite'
759
+ * console.log(result.model); // 'google/gemini-3.5-flash'
760
+ * console.log(result.routing.method); // 'portfolio'
713
761
  * console.log(result.routing.savings); // 0.78 (78% savings)
714
762
  * ```
715
763
  *
@@ -741,11 +789,15 @@ var LLMClient = class _LLMClient {
741
789
  routingProfile: options?.routingProfile
742
790
  });
743
791
  const tierConfigs = decision.tierConfigs ?? DEFAULT_ROUTING_CONFIG.tiers;
744
- const fullChain = getFallbackChain(decision.tier, tierConfigs);
745
- const fallbacks = fullChain.filter(
746
- (id) => id !== decision.model && modelPricing.has(id)
747
- );
748
- const response = await this.chat(decision.model, prompt, {
792
+ const ranked = decision.candidates?.length ? decision.candidates : [decision.model, ...getFallbackChain(decision.tier, tierConfigs)];
793
+ const callable = [];
794
+ for (const id of ranked) {
795
+ const resolved = !id.startsWith("free/") ? id : modelPricing.has(`nvidia/${id.slice(5)}`) ? `nvidia/${id.slice(5)}` : null;
796
+ if (resolved && !callable.includes(resolved)) callable.push(resolved);
797
+ }
798
+ const primary = callable[0] ?? decision.model;
799
+ const fallbacks = callable.slice(1);
800
+ const response = await this.chat(primary, prompt, {
749
801
  system: options?.system,
750
802
  maxTokens: options?.maxTokens,
751
803
  temperature: options?.temperature,
@@ -758,8 +810,8 @@ var LLMClient = class _LLMClient {
758
810
  });
759
811
  return {
760
812
  response,
761
- model: decision.model,
762
- routing: { ...decision, fallbacks }
813
+ model: primary,
814
+ routing: { ...decision, model: primary, fallbacks }
763
815
  };
764
816
  }
765
817
  /**
@@ -1783,20 +1835,38 @@ var LLMClient = class _LLMClient {
1783
1835
  }
1784
1836
  // ── PM convenience helpers (Predexon v2) ─────────────────────────────────
1785
1837
  // Thin wrappers over pm() / pmQuery() for the most common v2 endpoints.
1786
- /** List canonical cross-venue markets (Predexon v2). Tier 1 ($0.001/call).
1787
- * Filter with venue, status, category, league, event_id, pagination_key. */
1788
- async pmMarkets(params) {
1789
- return this.pm("markets", params);
1838
+ /** RETIRED — `/v1/pm/markets` no longer exists.
1839
+ *
1840
+ * Predexon sunset market matching on 2026-07-20 and the whole canonical layer
1841
+ * went with it, so this path returns 410 upstream. Use
1842
+ * `pm("markets/search", { q })` for cross-venue lookups.
1843
+ *
1844
+ * Kept as a throwing stub rather than deleted so upgrading does not break
1845
+ * property access; it throws before any network I/O.
1846
+ *
1847
+ * @throws {RetiredEndpointError} always. */
1848
+ async pmMarkets(_params) {
1849
+ throw new RetiredEndpointError(
1850
+ '/v1/pm/markets was sunset by Predexon on 2026-07-20 (upstream 410). Use pm("markets/search", { q }) for cross-venue lookups.'
1851
+ );
1790
1852
  }
1791
- /** List venue-native executable listings flattened across canonical markets
1792
- * (Predexon v2). Tier 1 ($0.001/call). */
1793
- async pmListings(params) {
1794
- return this.pm("markets/listings", params);
1853
+ /** RETIRED — `/v1/pm/markets/listings` no longer exists (410, sunset
1854
+ * 2026-07-20 with market matching). Use `pm("markets/search", { q })`.
1855
+ *
1856
+ * @throws {RetiredEndpointError} always. */
1857
+ async pmListings(_params) {
1858
+ throw new RetiredEndpointError(
1859
+ '/v1/pm/markets/listings was sunset by Predexon on 2026-07-20 (upstream 410). Use pm("markets/search", { q }) for cross-venue lookups.'
1860
+ );
1795
1861
  }
1796
- /** Resolve a canonical Predexon outcome ID to its market context and venue
1797
- * listings. Tier 1 ($0.001/call). */
1798
- async pmOutcome(predexonId) {
1799
- return this.pm(`outcomes/${predexonId}`);
1862
+ /** RETIRED — `/v1/pm/outcomes/{predexonId}` no longer exists (410, sunset
1863
+ * 2026-07-20 with market matching). Use `pm("markets/search", { q })`.
1864
+ *
1865
+ * @throws {RetiredEndpointError} always. */
1866
+ async pmOutcome(_predexonId) {
1867
+ throw new RetiredEndpointError(
1868
+ '/v1/pm/outcomes/{predexon_id} was sunset by Predexon on 2026-07-20 (upstream 410). Use pm("markets/search", { q }) for cross-venue lookups.'
1869
+ );
1800
1870
  }
1801
1871
  /** Polymarket markets with cursor-based keyset pagination (use pagination_key).
1802
1872
  * Tier 1 ($0.001/call). */
@@ -1808,12 +1878,18 @@ var LLMClient = class _LLMClient {
1808
1878
  async pmPolymarketEventsKeyset(params) {
1809
1879
  return this.pm("polymarket/events/keyset", params);
1810
1880
  }
1811
- /** List available sports categories. Tier 1 ($0.001/call). */
1881
+ /** List available sports categories. Tier 1 ($0.001/call).
1882
+ *
1883
+ * NOTE: upstream returns 500 for every `sports/*` path as of 2026-08-04.
1884
+ * The route still resolves, so this works again the moment Predexon restores
1885
+ * it, but do not build on it yet. */
1812
1886
  async pmSportsCategories() {
1813
1887
  return this.pm("sports/categories");
1814
1888
  }
1815
1889
  /** List sports markets grouped by game. Filter with league, sport_type,
1816
- * status, venue. Tier 1 ($0.001/call). */
1890
+ * status, venue. Tier 1 ($0.001/call).
1891
+ *
1892
+ * NOTE: upstream returns 500 for every `sports/*` path as of 2026-08-04. */
1817
1893
  async pmSportsMarkets(params) {
1818
1894
  return this.pm("sports/markets", params);
1819
1895
  }
@@ -4894,7 +4970,7 @@ var os3 = __toESM(require("os"), 1);
4894
4970
  var WALLET_DIR2 = path3.join(os3.homedir(), ".blockrun");
4895
4971
  var SOLANA_WALLET_FILE = path3.join(WALLET_DIR2, ".solana-session");
4896
4972
  async function createSolanaWallet() {
4897
- const { Keypair } = await import("@solana/web3.js");
4973
+ const { Keypair } = await loadSolanaWeb3("Solana wallet operations");
4898
4974
  const bs58 = await import("bs58");
4899
4975
  const keypair = Keypair.generate();
4900
4976
  return {
@@ -4951,7 +5027,7 @@ async function solanaKeyToBytes(privateKey) {
4951
5027
  }
4952
5028
  }
4953
5029
  async function solanaPublicKey(privateKey) {
4954
- const { Keypair } = await import("@solana/web3.js");
5030
+ const { Keypair } = await loadSolanaWeb3("Solana wallet operations");
4955
5031
  const bytes = await solanaKeyToBytes(privateKey);
4956
5032
  return Keypair.fromSecretKey(bytes).publicKey.toBase58();
4957
5033
  }
@@ -6245,6 +6321,7 @@ var AnthropicClient = class {
6245
6321
  PortraitClient,
6246
6322
  PriceClient,
6247
6323
  RPC_PRICE_USD,
6324
+ RetiredEndpointError,
6248
6325
  RpcClient,
6249
6326
  SOLANA_NETWORK,
6250
6327
  SOLANA_WALLET_FILE_PATH,