@blockrun/llm 1.15.0 → 2.0.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.cts CHANGED
@@ -242,6 +242,13 @@ interface ChatOptions {
242
242
  search?: boolean;
243
243
  /** Full Live Search configuration (for search-enabled models) */
244
244
  searchParameters?: SearchParameters;
245
+ /**
246
+ * Models to try in order if the primary returns a transient error
247
+ * (timeout, network, 5xx). 4xx and PaymentError still propagate
248
+ * immediately. `smartChat` populates this from the routing tier's
249
+ * fallback chain automatically.
250
+ */
251
+ fallbackModels?: string[];
245
252
  }
246
253
  interface ChatCompletionOptions {
247
254
  /** Max tokens to generate */
@@ -258,6 +265,12 @@ interface ChatCompletionOptions {
258
265
  tools?: Tool[];
259
266
  /** Tool selection strategy */
260
267
  toolChoice?: ToolChoice;
268
+ /**
269
+ * Models to try in order if the primary returns a transient error
270
+ * (timeout, network, 5xx). 4xx and PaymentError still propagate
271
+ * immediately.
272
+ */
273
+ fallbackModels?: string[];
261
274
  }
262
275
  type RoutingProfile = "free" | "eco" | "auto" | "premium";
263
276
  type RoutingTier = "SIMPLE" | "MEDIUM" | "COMPLEX" | "REASONING";
@@ -270,6 +283,12 @@ interface RoutingDecision {
270
283
  costEstimate: number;
271
284
  baselineCost: number;
272
285
  savings: number;
286
+ /**
287
+ * Remaining tier models with known pricing, in fallback order. `chat()`
288
+ * walks this list when the primary model hits a transient error
289
+ * (timeout, network, 5xx). Excludes the primary itself.
290
+ */
291
+ fallbacks?: string[];
273
292
  }
274
293
  interface SmartChatOptions extends ChatOptions {
275
294
  /** Routing profile: free (zero cost), eco (budget), auto (balanced), premium (best quality) */
@@ -689,29 +708,11 @@ declare class APIError extends BlockrunError {
689
708
  * BlockRun LLM Gateway Client.
690
709
  *
691
710
  * Provides access to multiple LLM providers (OpenAI, Anthropic, Google, etc.)
692
- * with automatic x402 micropayments on Base chain.
693
- *
694
- * Networks:
695
- * - Mainnet: https://blockrun.ai/api (Base, Chain ID 8453)
696
- * - Testnet: https://testnet.blockrun.ai/api (Base Sepolia, Chain ID 84532)
697
- *
698
- * @example Testnet usage
699
- * ```ts
700
- * // Use testnet convenience function
701
- * import { testnetClient } from '@blockrun/llm';
702
- * const client = testnetClient({ privateKey: '0x...' });
703
- * const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
704
- *
705
- * // Or configure manually
706
- * const client = new LLMClient({
707
- * privateKey: '0x...',
708
- * apiUrl: 'https://testnet.blockrun.ai/api'
709
- * });
710
- * ```
711
+ * with automatic x402 micropayments on Base chain (Mainnet, Chain ID 8453).
712
+ * API base: https://blockrun.ai/api
711
713
  */
712
714
  declare class LLMClient {
713
715
  static readonly DEFAULT_API_URL = "https://blockrun.ai/api";
714
- static readonly TESTNET_API_URL = "https://testnet.blockrun.ai/api";
715
716
  private account;
716
717
  private privateKey;
717
718
  private apiUrl;
@@ -779,17 +780,37 @@ declare class LLMClient {
779
780
  private getModelPricing;
780
781
  /**
781
782
  * Fetch model pricing from API.
783
+ *
784
+ * For flat-billed models (e.g. ZAI GLM-5 family at $0.001/call) the
785
+ * router still expects per-token rates, so we synthesise an equivalent
786
+ * per-token price assuming ~1500 total tokens per call. Without this,
787
+ * flat models would resolve to inputPrice=outputPrice=0 and the router
788
+ * would treat them as free, biasing routing decisions and reporting
789
+ * inflated savings %.
782
790
  */
783
791
  private fetchModelPricing;
784
792
  /**
785
793
  * Full chat completion interface (OpenAI-compatible).
786
794
  *
787
- * @param model - Model ID
795
+ * When `fallbackModels` is set, transient failures (timeouts, network
796
+ * errors, 5xx) on the primary model trigger a retry against the next
797
+ * model in the list before raising. 4xx errors and PaymentError
798
+ * propagate immediately — those aren't "swap upstream and retry"
799
+ * situations. Each fallback hop logs one stderr line.
800
+ *
801
+ * @param model - Primary model ID
788
802
  * @param messages - Array of messages with role and content
789
803
  * @param options - Optional completion parameters
790
804
  * @returns ChatResponse object with choices and usage
791
805
  */
792
806
  chatCompletion(model: string, messages: ChatMessage[], options?: ChatCompletionOptions): Promise<ChatResponse>;
807
+ /**
808
+ * Write a canonical cost_log entry after a settled x402 payment.
809
+ * Best-effort: failures here must never break a successful API call.
810
+ * Mirrors what Franklin's AgentClient writes via src/agent/llm.ts so
811
+ * cost_log.jsonl is a single source of truth regardless of caller.
812
+ */
813
+ private recordCost;
793
814
  /**
794
815
  * Make a request with automatic x402 payment handling.
795
816
  */
@@ -836,29 +857,37 @@ declare class LLMClient {
836
857
  */
837
858
  private fetchWithTimeout;
838
859
  /**
839
- * List available LLM models with pricing.
860
+ * List available models with pricing.
861
+ *
862
+ * Returns the full `/v1/models` unified catalog (chat + image + music).
863
+ * The shape preserves backwards compatibility — image/music rows have
864
+ * `inputPrice = outputPrice = 0` since those fields don't apply, and
865
+ * their per-call price surfaces via `flatPrice`.
840
866
  */
841
867
  listModels(): Promise<Model[]>;
842
868
  /**
843
869
  * List available image generation models with pricing.
870
+ *
871
+ * The dedicated `/v1/images/models` endpoint was deprecated server-side;
872
+ * image models live in the unified `/v1/models` catalog under
873
+ * `categories: ["image", ...]`. This method filters that catalog so
874
+ * existing callers keep working.
844
875
  */
845
876
  listImageModels(): Promise<ImageModel[]>;
846
877
  /**
847
- * List all available models (both LLM and image) with pricing.
878
+ * List all available models (chat, image, music, etc.) with pricing.
848
879
  *
849
- * @returns Array of all models with 'type' field ('llm' or 'image')
850
- *
851
- * @example
852
- * const models = await client.listAllModels();
853
- * for (const model of models) {
854
- * if (model.type === 'llm') {
855
- * console.log(`LLM: ${model.id} - $${model.inputPrice}/M input`);
856
- * } else {
857
- * console.log(`Image: ${model.id} - $${model.pricePerImage}/image`);
858
- * }
859
- * }
880
+ * @returns Array of all models with `type` field set from category
881
+ * (`llm` for chat, `image` / `music` for media). Backwards-compat:
882
+ * chat models always report `type: "llm"`.
860
883
  */
861
884
  listAllModels(): Promise<(Model | ImageModel)[]>;
885
+ /**
886
+ * Internal: fetch the raw `/v1/models` catalog without normalising shape.
887
+ * Used by listImageModels / listAllModels so each can pick category-
888
+ * specific fields.
889
+ */
890
+ private fetchRawModels;
862
891
  /**
863
892
  * Edit an image using img2img.
864
893
  *
@@ -876,6 +905,17 @@ declare class LLMClient {
876
905
  * @returns SearchResult with summary and citations
877
906
  */
878
907
  search(query: string, options?: SearchOptions): Promise<SearchResult>;
908
+ /**
909
+ * Generic Exa endpoint proxy (POST). Useful when you need an Exa API
910
+ * surface that the typed wrappers below don't expose.
911
+ *
912
+ * @param path - Exa endpoint segment: "search" | "find-similar" | "contents" | "answer"
913
+ * @param body - Request body (see Exa API docs)
914
+ *
915
+ * @example
916
+ * const results = await client.exa("search", { query: "latest AI research", numResults: 5 });
917
+ */
918
+ exa(path: string, body: Record<string, unknown>): Promise<Record<string, unknown>>;
879
919
  /**
880
920
  * Neural web search via Exa. Returns semantically relevant URLs and metadata.
881
921
  * Understands meaning, not just keywords. $0.01/call.
@@ -907,9 +947,7 @@ declare class LLMClient {
907
947
  */
908
948
  exaFindSimilar(url: string, options?: ExaFindSimilarOptions): Promise<ExaSearchResponse>;
909
949
  /**
910
- * Get USDC balance on Base network.
911
- *
912
- * Automatically detects mainnet vs testnet based on API URL.
950
+ * Get USDC balance on Base mainnet.
913
951
  *
914
952
  * @returns USDC balance as a float (6 decimal places normalized)
915
953
  *
@@ -1120,38 +1158,7 @@ declare class LLMClient {
1120
1158
  * Get the wallet address being used for payments.
1121
1159
  */
1122
1160
  getWalletAddress(): string;
1123
- /**
1124
- * Check if client is configured for testnet.
1125
- */
1126
- isTestnet(): boolean;
1127
1161
  }
1128
- /**
1129
- * Create a testnet LLM client for development and testing.
1130
- *
1131
- * This is a convenience function that creates an LLMClient configured
1132
- * for the BlockRun testnet (Base Sepolia).
1133
- *
1134
- * @param options - Client options (privateKey required unless BASE_CHAIN_WALLET_KEY env var is set)
1135
- * @returns LLMClient configured for testnet
1136
- *
1137
- * @example
1138
- * ```ts
1139
- * import { testnetClient } from '@blockrun/llm';
1140
- *
1141
- * const client = testnetClient({ privateKey: '0x...' });
1142
- * const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
1143
- * ```
1144
- *
1145
- * Testnet Setup:
1146
- * 1. Get testnet ETH from https://www.alchemy.com/faucets/base-sepolia
1147
- * 2. Get testnet USDC from https://faucet.circle.com/
1148
- * 3. Use your wallet with testnet funds
1149
- *
1150
- * Available Testnet Models:
1151
- * - openai/gpt-oss-20b
1152
- * - openai/gpt-oss-120b
1153
- */
1154
- declare function testnetClient(options?: Omit<LLMClientOptions, 'apiUrl'>): LLMClient;
1155
1162
 
1156
1163
  /**
1157
1164
  * BlockRun Image Client - Generate images via x402 micropayments.
@@ -1216,6 +1223,11 @@ declare class ImageClient {
1216
1223
  edit(prompt: string, image: string, options?: ImageEditOptions): Promise<ImageResponse>;
1217
1224
  /**
1218
1225
  * List available image generation models with pricing.
1226
+ *
1227
+ * The dedicated `/v1/images/models` endpoint was deprecated server-side;
1228
+ * image models live in the unified `/v1/models` catalog under
1229
+ * `categories: ["image", ...]`. This method filters that catalog so
1230
+ * existing callers keep working.
1219
1231
  */
1220
1232
  listImageModels(): Promise<ImageModel[]>;
1221
1233
  /**
@@ -1850,18 +1862,29 @@ declare function status(): Promise<{
1850
1862
  balance: number;
1851
1863
  }>;
1852
1864
 
1865
+ /** Canonical on-wire schema for cost_log.jsonl entries. */
1853
1866
  interface CostEntry {
1854
- timestamp: string;
1855
- model: string;
1856
- inputTokens: number;
1857
- outputTokens: number;
1858
- costUsd: number;
1867
+ /** Unix epoch seconds (float, millisecond precision). */
1868
+ ts: number;
1869
+ /** API endpoint path, e.g. "/v1/chat/completions". */
1870
+ endpoint: string;
1871
+ /** Settled USDC amount (USD, 6-decimal precision). */
1872
+ cost_usd: number;
1873
+ /** Model id when known, e.g. "zai/glm-5-turbo". Optional for non-LLM endpoints. */
1874
+ model?: string;
1875
+ /** Payer wallet address (EVM 0x... or Solana base58). */
1876
+ wallet?: string;
1877
+ /** Network identifier — "eip155:8453" for Base mainnet, "solana-mainnet", etc. */
1878
+ network?: string;
1879
+ /** Caller kind for analytics — "LLMClient", "ImageClient", "AgentClient", ... */
1880
+ client_kind?: string;
1859
1881
  }
1860
1882
  declare function logCost(entry: CostEntry): void;
1861
1883
  declare function getCostSummary(): {
1862
1884
  totalUsd: number;
1863
1885
  calls: number;
1864
1886
  byModel: Record<string, number>;
1887
+ byEndpoint: Record<string, number>;
1865
1888
  };
1866
1889
 
1867
1890
  /**
@@ -2077,4 +2100,4 @@ declare function validateTemperature(temperature?: number): void;
2077
2100
  */
2078
2101
  declare function validateTopP(topP?: number): void;
2079
2102
 
2080
- 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, 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, testnetClient, validateMaxTokens, validateModel, validateTemperature, validateTopP };
2103
+ 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, 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 };
package/dist/index.d.ts CHANGED
@@ -242,6 +242,13 @@ interface ChatOptions {
242
242
  search?: boolean;
243
243
  /** Full Live Search configuration (for search-enabled models) */
244
244
  searchParameters?: SearchParameters;
245
+ /**
246
+ * Models to try in order if the primary returns a transient error
247
+ * (timeout, network, 5xx). 4xx and PaymentError still propagate
248
+ * immediately. `smartChat` populates this from the routing tier's
249
+ * fallback chain automatically.
250
+ */
251
+ fallbackModels?: string[];
245
252
  }
246
253
  interface ChatCompletionOptions {
247
254
  /** Max tokens to generate */
@@ -258,6 +265,12 @@ interface ChatCompletionOptions {
258
265
  tools?: Tool[];
259
266
  /** Tool selection strategy */
260
267
  toolChoice?: ToolChoice;
268
+ /**
269
+ * Models to try in order if the primary returns a transient error
270
+ * (timeout, network, 5xx). 4xx and PaymentError still propagate
271
+ * immediately.
272
+ */
273
+ fallbackModels?: string[];
261
274
  }
262
275
  type RoutingProfile = "free" | "eco" | "auto" | "premium";
263
276
  type RoutingTier = "SIMPLE" | "MEDIUM" | "COMPLEX" | "REASONING";
@@ -270,6 +283,12 @@ interface RoutingDecision {
270
283
  costEstimate: number;
271
284
  baselineCost: number;
272
285
  savings: number;
286
+ /**
287
+ * Remaining tier models with known pricing, in fallback order. `chat()`
288
+ * walks this list when the primary model hits a transient error
289
+ * (timeout, network, 5xx). Excludes the primary itself.
290
+ */
291
+ fallbacks?: string[];
273
292
  }
274
293
  interface SmartChatOptions extends ChatOptions {
275
294
  /** Routing profile: free (zero cost), eco (budget), auto (balanced), premium (best quality) */
@@ -689,29 +708,11 @@ declare class APIError extends BlockrunError {
689
708
  * BlockRun LLM Gateway Client.
690
709
  *
691
710
  * Provides access to multiple LLM providers (OpenAI, Anthropic, Google, etc.)
692
- * with automatic x402 micropayments on Base chain.
693
- *
694
- * Networks:
695
- * - Mainnet: https://blockrun.ai/api (Base, Chain ID 8453)
696
- * - Testnet: https://testnet.blockrun.ai/api (Base Sepolia, Chain ID 84532)
697
- *
698
- * @example Testnet usage
699
- * ```ts
700
- * // Use testnet convenience function
701
- * import { testnetClient } from '@blockrun/llm';
702
- * const client = testnetClient({ privateKey: '0x...' });
703
- * const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
704
- *
705
- * // Or configure manually
706
- * const client = new LLMClient({
707
- * privateKey: '0x...',
708
- * apiUrl: 'https://testnet.blockrun.ai/api'
709
- * });
710
- * ```
711
+ * with automatic x402 micropayments on Base chain (Mainnet, Chain ID 8453).
712
+ * API base: https://blockrun.ai/api
711
713
  */
712
714
  declare class LLMClient {
713
715
  static readonly DEFAULT_API_URL = "https://blockrun.ai/api";
714
- static readonly TESTNET_API_URL = "https://testnet.blockrun.ai/api";
715
716
  private account;
716
717
  private privateKey;
717
718
  private apiUrl;
@@ -779,17 +780,37 @@ declare class LLMClient {
779
780
  private getModelPricing;
780
781
  /**
781
782
  * Fetch model pricing from API.
783
+ *
784
+ * For flat-billed models (e.g. ZAI GLM-5 family at $0.001/call) the
785
+ * router still expects per-token rates, so we synthesise an equivalent
786
+ * per-token price assuming ~1500 total tokens per call. Without this,
787
+ * flat models would resolve to inputPrice=outputPrice=0 and the router
788
+ * would treat them as free, biasing routing decisions and reporting
789
+ * inflated savings %.
782
790
  */
783
791
  private fetchModelPricing;
784
792
  /**
785
793
  * Full chat completion interface (OpenAI-compatible).
786
794
  *
787
- * @param model - Model ID
795
+ * When `fallbackModels` is set, transient failures (timeouts, network
796
+ * errors, 5xx) on the primary model trigger a retry against the next
797
+ * model in the list before raising. 4xx errors and PaymentError
798
+ * propagate immediately — those aren't "swap upstream and retry"
799
+ * situations. Each fallback hop logs one stderr line.
800
+ *
801
+ * @param model - Primary model ID
788
802
  * @param messages - Array of messages with role and content
789
803
  * @param options - Optional completion parameters
790
804
  * @returns ChatResponse object with choices and usage
791
805
  */
792
806
  chatCompletion(model: string, messages: ChatMessage[], options?: ChatCompletionOptions): Promise<ChatResponse>;
807
+ /**
808
+ * Write a canonical cost_log entry after a settled x402 payment.
809
+ * Best-effort: failures here must never break a successful API call.
810
+ * Mirrors what Franklin's AgentClient writes via src/agent/llm.ts so
811
+ * cost_log.jsonl is a single source of truth regardless of caller.
812
+ */
813
+ private recordCost;
793
814
  /**
794
815
  * Make a request with automatic x402 payment handling.
795
816
  */
@@ -836,29 +857,37 @@ declare class LLMClient {
836
857
  */
837
858
  private fetchWithTimeout;
838
859
  /**
839
- * List available LLM models with pricing.
860
+ * List available models with pricing.
861
+ *
862
+ * Returns the full `/v1/models` unified catalog (chat + image + music).
863
+ * The shape preserves backwards compatibility — image/music rows have
864
+ * `inputPrice = outputPrice = 0` since those fields don't apply, and
865
+ * their per-call price surfaces via `flatPrice`.
840
866
  */
841
867
  listModels(): Promise<Model[]>;
842
868
  /**
843
869
  * List available image generation models with pricing.
870
+ *
871
+ * The dedicated `/v1/images/models` endpoint was deprecated server-side;
872
+ * image models live in the unified `/v1/models` catalog under
873
+ * `categories: ["image", ...]`. This method filters that catalog so
874
+ * existing callers keep working.
844
875
  */
845
876
  listImageModels(): Promise<ImageModel[]>;
846
877
  /**
847
- * List all available models (both LLM and image) with pricing.
878
+ * List all available models (chat, image, music, etc.) with pricing.
848
879
  *
849
- * @returns Array of all models with 'type' field ('llm' or 'image')
850
- *
851
- * @example
852
- * const models = await client.listAllModels();
853
- * for (const model of models) {
854
- * if (model.type === 'llm') {
855
- * console.log(`LLM: ${model.id} - $${model.inputPrice}/M input`);
856
- * } else {
857
- * console.log(`Image: ${model.id} - $${model.pricePerImage}/image`);
858
- * }
859
- * }
880
+ * @returns Array of all models with `type` field set from category
881
+ * (`llm` for chat, `image` / `music` for media). Backwards-compat:
882
+ * chat models always report `type: "llm"`.
860
883
  */
861
884
  listAllModels(): Promise<(Model | ImageModel)[]>;
885
+ /**
886
+ * Internal: fetch the raw `/v1/models` catalog without normalising shape.
887
+ * Used by listImageModels / listAllModels so each can pick category-
888
+ * specific fields.
889
+ */
890
+ private fetchRawModels;
862
891
  /**
863
892
  * Edit an image using img2img.
864
893
  *
@@ -876,6 +905,17 @@ declare class LLMClient {
876
905
  * @returns SearchResult with summary and citations
877
906
  */
878
907
  search(query: string, options?: SearchOptions): Promise<SearchResult>;
908
+ /**
909
+ * Generic Exa endpoint proxy (POST). Useful when you need an Exa API
910
+ * surface that the typed wrappers below don't expose.
911
+ *
912
+ * @param path - Exa endpoint segment: "search" | "find-similar" | "contents" | "answer"
913
+ * @param body - Request body (see Exa API docs)
914
+ *
915
+ * @example
916
+ * const results = await client.exa("search", { query: "latest AI research", numResults: 5 });
917
+ */
918
+ exa(path: string, body: Record<string, unknown>): Promise<Record<string, unknown>>;
879
919
  /**
880
920
  * Neural web search via Exa. Returns semantically relevant URLs and metadata.
881
921
  * Understands meaning, not just keywords. $0.01/call.
@@ -907,9 +947,7 @@ declare class LLMClient {
907
947
  */
908
948
  exaFindSimilar(url: string, options?: ExaFindSimilarOptions): Promise<ExaSearchResponse>;
909
949
  /**
910
- * Get USDC balance on Base network.
911
- *
912
- * Automatically detects mainnet vs testnet based on API URL.
950
+ * Get USDC balance on Base mainnet.
913
951
  *
914
952
  * @returns USDC balance as a float (6 decimal places normalized)
915
953
  *
@@ -1120,38 +1158,7 @@ declare class LLMClient {
1120
1158
  * Get the wallet address being used for payments.
1121
1159
  */
1122
1160
  getWalletAddress(): string;
1123
- /**
1124
- * Check if client is configured for testnet.
1125
- */
1126
- isTestnet(): boolean;
1127
1161
  }
1128
- /**
1129
- * Create a testnet LLM client for development and testing.
1130
- *
1131
- * This is a convenience function that creates an LLMClient configured
1132
- * for the BlockRun testnet (Base Sepolia).
1133
- *
1134
- * @param options - Client options (privateKey required unless BASE_CHAIN_WALLET_KEY env var is set)
1135
- * @returns LLMClient configured for testnet
1136
- *
1137
- * @example
1138
- * ```ts
1139
- * import { testnetClient } from '@blockrun/llm';
1140
- *
1141
- * const client = testnetClient({ privateKey: '0x...' });
1142
- * const response = await client.chat('openai/gpt-oss-20b', 'Hello!');
1143
- * ```
1144
- *
1145
- * Testnet Setup:
1146
- * 1. Get testnet ETH from https://www.alchemy.com/faucets/base-sepolia
1147
- * 2. Get testnet USDC from https://faucet.circle.com/
1148
- * 3. Use your wallet with testnet funds
1149
- *
1150
- * Available Testnet Models:
1151
- * - openai/gpt-oss-20b
1152
- * - openai/gpt-oss-120b
1153
- */
1154
- declare function testnetClient(options?: Omit<LLMClientOptions, 'apiUrl'>): LLMClient;
1155
1162
 
1156
1163
  /**
1157
1164
  * BlockRun Image Client - Generate images via x402 micropayments.
@@ -1216,6 +1223,11 @@ declare class ImageClient {
1216
1223
  edit(prompt: string, image: string, options?: ImageEditOptions): Promise<ImageResponse>;
1217
1224
  /**
1218
1225
  * List available image generation models with pricing.
1226
+ *
1227
+ * The dedicated `/v1/images/models` endpoint was deprecated server-side;
1228
+ * image models live in the unified `/v1/models` catalog under
1229
+ * `categories: ["image", ...]`. This method filters that catalog so
1230
+ * existing callers keep working.
1219
1231
  */
1220
1232
  listImageModels(): Promise<ImageModel[]>;
1221
1233
  /**
@@ -1850,18 +1862,29 @@ declare function status(): Promise<{
1850
1862
  balance: number;
1851
1863
  }>;
1852
1864
 
1865
+ /** Canonical on-wire schema for cost_log.jsonl entries. */
1853
1866
  interface CostEntry {
1854
- timestamp: string;
1855
- model: string;
1856
- inputTokens: number;
1857
- outputTokens: number;
1858
- costUsd: number;
1867
+ /** Unix epoch seconds (float, millisecond precision). */
1868
+ ts: number;
1869
+ /** API endpoint path, e.g. "/v1/chat/completions". */
1870
+ endpoint: string;
1871
+ /** Settled USDC amount (USD, 6-decimal precision). */
1872
+ cost_usd: number;
1873
+ /** Model id when known, e.g. "zai/glm-5-turbo". Optional for non-LLM endpoints. */
1874
+ model?: string;
1875
+ /** Payer wallet address (EVM 0x... or Solana base58). */
1876
+ wallet?: string;
1877
+ /** Network identifier — "eip155:8453" for Base mainnet, "solana-mainnet", etc. */
1878
+ network?: string;
1879
+ /** Caller kind for analytics — "LLMClient", "ImageClient", "AgentClient", ... */
1880
+ client_kind?: string;
1859
1881
  }
1860
1882
  declare function logCost(entry: CostEntry): void;
1861
1883
  declare function getCostSummary(): {
1862
1884
  totalUsd: number;
1863
1885
  calls: number;
1864
1886
  byModel: Record<string, number>;
1887
+ byEndpoint: Record<string, number>;
1865
1888
  };
1866
1889
 
1867
1890
  /**
@@ -2077,4 +2100,4 @@ declare function validateTemperature(temperature?: number): void;
2077
2100
  */
2078
2101
  declare function validateTopP(topP?: number): void;
2079
2102
 
2080
- 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, 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, testnetClient, validateMaxTokens, validateModel, validateTemperature, validateTopP };
2103
+ 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, 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 };