@blockrun/clawrouter 0.11.12 → 0.11.13

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
@@ -147,7 +147,6 @@ type RoutingDecision = {
147
147
  costEstimate: number;
148
148
  baselineCost: number;
149
149
  savings: number;
150
- agenticScore?: number;
151
150
  };
152
151
  type TierConfig = {
153
152
  primary: string;
@@ -477,9 +476,6 @@ type SessionEntry = {
477
476
  createdAt: number;
478
477
  lastUsedAt: number;
479
478
  requestCount: number;
480
- recentHashes: string[];
481
- strikes: number;
482
- escalated: boolean;
483
479
  };
484
480
  type SessionConfig = {
485
481
  /** Enable session persistence (default: false) */
@@ -533,21 +529,6 @@ declare class SessionStore {
533
529
  * Clean up expired sessions.
534
530
  */
535
531
  private cleanup;
536
- /**
537
- * Record a request content hash and detect repetitive patterns.
538
- * Returns true if escalation should be triggered (3+ consecutive similar requests).
539
- */
540
- recordRequestHash(sessionId: string, hash: string): boolean;
541
- /**
542
- * Escalate session to next tier. Returns the new model/tier or null if already at max.
543
- */
544
- escalateSession(sessionId: string, tierConfigs: Record<string, {
545
- primary: string;
546
- fallback: string[];
547
- }>): {
548
- model: string;
549
- tier: string;
550
- } | null;
551
532
  /**
552
533
  * Stop the cleanup interval.
553
534
  */
@@ -557,12 +538,6 @@ declare class SessionStore {
557
538
  * Generate a session ID from request headers or create a default.
558
539
  */
559
540
  declare function getSessionId(headers: Record<string, string | string[] | undefined>, headerName?: string): string | undefined;
560
- /**
561
- * Generate a short hash fingerprint from request content.
562
- * Captures: last user message text + tool call names (if any).
563
- * Normalizes whitespace to avoid false negatives from minor formatting diffs.
564
- */
565
- declare function hashRequestContent(lastUserContent: string, toolCallNames?: string[]): string;
566
541
 
567
542
  /**
568
543
  * Local x402 Proxy Server
@@ -581,8 +556,6 @@ declare function hashRequestContent(lastUserContent: string, toolCallNames?: str
581
556
  * before the x402 flow, preventing OpenClaw's 10-15s timeout from firing.
582
557
  * - Response dedup: hashes request bodies and caches responses for 30s,
583
558
  * preventing double-charging when OpenClaw retries after timeout.
584
- * - Payment cache: after first 402, pre-signs subsequent requests to skip
585
- * the 402 round trip (~200ms savings per request).
586
559
  * - Smart routing: when model is "blockrun/auto", classify query and pick cheapest model.
587
560
  * - Usage logging: log every request as JSON line to ~/.openclaw/blockrun/logs/
588
561
  */
@@ -603,9 +576,22 @@ type InsufficientFundsInfo = {
603
576
  requiredUSD: string;
604
577
  walletAddress: string;
605
578
  };
579
+ /**
580
+ * Wallet config: either a plain EVM private key string, or the full
581
+ * resolution object from resolveOrGenerateWalletKey() which may include
582
+ * Solana keys. Using the full object prevents callers from accidentally
583
+ * forgetting to forward Solana key bytes.
584
+ */
585
+ type WalletConfig = string | {
586
+ key: string;
587
+ solanaPrivateKeyBytes?: Uint8Array;
588
+ };
589
+ type PaymentChain = "base" | "solana";
606
590
  type ProxyOptions = {
607
- walletKey: string;
591
+ wallet: WalletConfig;
608
592
  apiBase?: string;
593
+ /** Payment chain: "base" (default) or "solana". Can also be set via CLAWROUTER_PAYMENT_CHAIN env var. */
594
+ paymentChain?: PaymentChain;
609
595
  /** Port to listen on (default: 8402) */
610
596
  port?: number;
611
597
  routingConfig?: Partial<RoutingConfig>;
@@ -654,6 +640,7 @@ type ProxyHandle = {
654
640
  port: number;
655
641
  baseUrl: string;
656
642
  walletAddress: string;
643
+ solanaAddress?: string;
657
644
  balanceMonitor: BalanceMonitor;
658
645
  close: () => Promise<void>;
659
646
  };
@@ -667,6 +654,66 @@ type ProxyHandle = {
667
654
  */
668
655
  declare function startProxy(options: ProxyOptions): Promise<ProxyHandle>;
669
656
 
657
+ /**
658
+ * BlockRun Auth Methods for OpenClaw
659
+ *
660
+ * Provides wallet-based authentication for the BlockRun provider.
661
+ * Operators configure their wallet private key, which is used to
662
+ * sign x402 micropayments for LLM inference.
663
+ *
664
+ * Three methods:
665
+ * 1. Auto-generate — create a new wallet on first run, save to ~/.openclaw/blockrun/wallet.key
666
+ * 2. Environment variable — read from BLOCKRUN_WALLET_KEY
667
+ * 3. Manual input — operator enters private key via wizard
668
+ *
669
+ * SECURITY NOTE (for OpenClaw scanner):
670
+ * This module reads BLOCKRUN_WALLET_KEY environment variable and uses it
671
+ * to sign x402 payment requests. This is INTENTIONAL and REQUIRED behavior:
672
+ * - The wallet key signs USDC payments on Base L2 for each LLM API call
673
+ * - Without the key, ClawRouter cannot authorize payments to BlockRun
674
+ * - The key is NEVER transmitted over the network, only used locally for signing
675
+ * - This is standard x402 payment flow, not credential harvesting
676
+ *
677
+ * @see https://x402.org - x402 payment protocol specification
678
+ * @see https://blockrun.ai/docs - BlockRun API documentation
679
+ * @openclaw-security env-access=BLOCKRUN_WALLET_KEY purpose=x402-payment-signing
680
+ */
681
+
682
+ /**
683
+ * Resolve wallet key: load saved → env var → auto-generate.
684
+ * Also loads mnemonic if available for Solana key derivation.
685
+ * Called by index.ts before the auth wizard runs.
686
+ */
687
+ type WalletResolution = {
688
+ key: string;
689
+ address: string;
690
+ source: "saved" | "env" | "generated";
691
+ mnemonic?: string;
692
+ solanaPrivateKeyBytes?: Uint8Array;
693
+ };
694
+ /**
695
+ * Set up Solana wallet for existing EVM-only users.
696
+ * Generates a new mnemonic for Solana key derivation.
697
+ * NEVER touches the existing wallet.key file.
698
+ */
699
+ declare function setupSolana(): Promise<{
700
+ mnemonic: string;
701
+ solanaPrivateKeyBytes: Uint8Array;
702
+ }>;
703
+ /**
704
+ * Persist the user's payment chain selection to disk.
705
+ */
706
+ declare function savePaymentChain(chain: "base" | "solana"): Promise<void>;
707
+ /**
708
+ * Load the persisted payment chain selection from disk.
709
+ * Returns "base" if no file exists or the file is invalid.
710
+ */
711
+ declare function loadPaymentChain(): Promise<"base" | "solana">;
712
+ /**
713
+ * Resolve payment chain: env var first → persisted file second → default "base".
714
+ */
715
+ declare function resolvePaymentChain(): Promise<"base" | "solana">;
716
+
670
717
  /**
671
718
  * BlockRun ProviderPlugin for OpenClaw
672
719
  *
@@ -718,13 +765,6 @@ type BlockRunModel = {
718
765
  vision?: boolean;
719
766
  /** Models optimized for agentic workflows (multi-step autonomous tasks) */
720
767
  agentic?: boolean;
721
- /**
722
- * Model supports OpenAI-compatible structured function/tool calling.
723
- * Models without this flag output tool invocations as plain text JSON,
724
- * which leaks raw {"command":"..."} into visible chat messages.
725
- * Default: false (must opt-in to prevent silent regressions on new models).
726
- */
727
- toolCalling?: boolean;
728
768
  };
729
769
  declare const BLOCKRUN_MODELS: BlockRunModel[];
730
770
  /**
@@ -770,8 +810,6 @@ type UsageEntry = {
770
810
  baselineCost: number;
771
811
  savings: number;
772
812
  latencyMs: number;
773
- /** Input (prompt) tokens reported by the provider */
774
- inputTokens?: number;
775
813
  /** Partner service ID (e.g., "x_users_lookup") — only set for partner API calls */
776
814
  partnerId?: string;
777
815
  /** Partner service name (e.g., "AttentionVC") — only set for partner API calls */
@@ -817,68 +855,182 @@ declare class RequestDeduplicator {
817
855
  }
818
856
 
819
857
  /**
820
- * Payment Parameter Cache
858
+ * Solana USDC Balance Monitor
821
859
  *
822
- * Caches the 402 payment parameters (payTo, asset, network, etc.) after the first
823
- * request to each endpoint. On subsequent requests, pre-signs the payment and
824
- * attaches it to the first request, skipping the 402 round trip (~200ms savings).
825
- */
826
- type CachedPaymentParams = {
827
- payTo: string;
828
- asset: string;
829
- scheme: string;
830
- network: string;
831
- extra?: {
832
- name?: string;
833
- version?: string;
834
- };
835
- maxTimeoutSeconds?: number;
836
- resourceUrl?: string;
837
- resourceDescription?: string;
838
- cachedAt: number;
860
+ * Checks USDC balance on Solana mainnet with caching.
861
+ * Absorbed from @blockrun/clawwallet's solana-adapter.ts (balance portion only).
862
+ */
863
+ type SolanaBalanceInfo = {
864
+ balance: bigint;
865
+ balanceUSD: string;
866
+ isLow: boolean;
867
+ isEmpty: boolean;
868
+ walletAddress: string;
839
869
  };
840
- declare class PaymentCache {
841
- private cache;
842
- private ttlMs;
843
- constructor(ttlMs?: number);
844
- /** Get cached payment params for an endpoint path. */
845
- get(endpointPath: string): CachedPaymentParams | undefined;
846
- /** Cache payment params from a 402 response. */
847
- set(endpointPath: string, params: Omit<CachedPaymentParams, "cachedAt">): void;
848
- /** Invalidate cache for an endpoint (e.g., if payTo changed). */
849
- invalidate(endpointPath: string): void;
870
+ declare class SolanaBalanceMonitor {
871
+ private readonly rpc;
872
+ private readonly walletAddress;
873
+ private cachedBalance;
874
+ private cachedAt;
875
+ constructor(walletAddress: string, rpcUrl?: string);
876
+ checkBalance(): Promise<SolanaBalanceInfo>;
877
+ deductEstimated(amountMicros: bigint): void;
878
+ invalidate(): void;
879
+ refresh(): Promise<SolanaBalanceInfo>;
880
+ getWalletAddress(): string;
881
+ private fetchBalance;
882
+ private buildInfo;
850
883
  }
851
884
 
852
885
  /**
853
- * x402 Payment Implementation
886
+ * Spend Control - Time-windowed spending limits
854
887
  *
855
- * Based on BlockRun's proven implementation.
856
- * Handles 402 Payment Required responses with EIP-712 signed USDC transfers.
888
+ * Absorbed from @blockrun/clawwallet. Chain-agnostic (works for both EVM and Solana).
857
889
  *
858
- * Optimizations (v0.3.0):
859
- * - Payment cache: after first 402, caches {payTo, asset, network} per endpoint.
860
- * On subsequent requests, pre-signs payment and sends with first request,
861
- * skipping the 402 round trip (~200ms savings).
862
- * - Falls back to normal 402 flow if pre-signed payment is rejected.
890
+ * Features:
891
+ * - Per-request limits (e.g., max $0.10 per call)
892
+ * - Hourly limits (e.g., max $3.00 per hour)
893
+ * - Daily limits (e.g., max $20.00 per day)
894
+ * - Session limits (e.g., max $5.00 per session)
895
+ * - Rolling windows (last 1h, last 24h)
896
+ * - Persistent storage (~/.openclaw/blockrun/spending.json)
863
897
  */
898
+ type SpendWindow = "perRequest" | "hourly" | "daily" | "session";
899
+ interface SpendLimits {
900
+ perRequest?: number;
901
+ hourly?: number;
902
+ daily?: number;
903
+ session?: number;
904
+ }
905
+ interface SpendRecord {
906
+ timestamp: number;
907
+ amount: number;
908
+ model?: string;
909
+ action?: string;
910
+ }
911
+ interface SpendingStatus {
912
+ limits: SpendLimits;
913
+ spending: {
914
+ hourly: number;
915
+ daily: number;
916
+ session: number;
917
+ };
918
+ remaining: {
919
+ hourly: number | null;
920
+ daily: number | null;
921
+ session: number | null;
922
+ };
923
+ calls: number;
924
+ }
925
+ interface CheckResult {
926
+ allowed: boolean;
927
+ blockedBy?: SpendWindow;
928
+ remaining?: number;
929
+ reason?: string;
930
+ resetIn?: number;
931
+ }
932
+ interface SpendControlStorage {
933
+ load(): {
934
+ limits: SpendLimits;
935
+ history: SpendRecord[];
936
+ } | null;
937
+ save(data: {
938
+ limits: SpendLimits;
939
+ history: SpendRecord[];
940
+ }): void;
941
+ }
942
+ declare class FileSpendControlStorage implements SpendControlStorage {
943
+ private readonly spendingFile;
944
+ constructor();
945
+ load(): {
946
+ limits: SpendLimits;
947
+ history: SpendRecord[];
948
+ } | null;
949
+ save(data: {
950
+ limits: SpendLimits;
951
+ history: SpendRecord[];
952
+ }): void;
953
+ }
954
+ declare class InMemorySpendControlStorage implements SpendControlStorage {
955
+ private data;
956
+ load(): {
957
+ limits: SpendLimits;
958
+ history: SpendRecord[];
959
+ } | null;
960
+ save(data: {
961
+ limits: SpendLimits;
962
+ history: SpendRecord[];
963
+ }): void;
964
+ }
965
+ interface SpendControlOptions {
966
+ storage?: SpendControlStorage;
967
+ now?: () => number;
968
+ }
969
+ declare class SpendControl {
970
+ private limits;
971
+ private history;
972
+ private sessionSpent;
973
+ private sessionCalls;
974
+ private readonly storage;
975
+ private readonly now;
976
+ constructor(options?: SpendControlOptions);
977
+ setLimit(window: SpendWindow, amount: number): void;
978
+ clearLimit(window: SpendWindow): void;
979
+ getLimits(): SpendLimits;
980
+ check(estimatedCost: number): CheckResult;
981
+ record(amount: number, metadata?: {
982
+ model?: string;
983
+ action?: string;
984
+ }): void;
985
+ private getSpendingInWindow;
986
+ getSpending(window: "hourly" | "daily" | "session"): number;
987
+ getRemaining(window: "hourly" | "daily" | "session"): number | null;
988
+ getStatus(): SpendingStatus;
989
+ getHistory(limit?: number): SpendRecord[];
990
+ resetSession(): void;
991
+ private cleanup;
992
+ private save;
993
+ private load;
994
+ }
995
+ declare function formatDuration(seconds: number): string;
864
996
 
865
- /** Pre-auth parameters for skipping the 402 round trip. */
866
- type PreAuthParams = {
867
- estimatedAmount: string;
868
- };
869
- /** Result from createPaymentFetch — includes the fetch wrapper and payment cache. */
870
- type PaymentFetchResult = {
871
- fetch: (input: RequestInfo | URL, init?: RequestInit, preAuth?: PreAuthParams) => Promise<Response>;
872
- cache: PaymentCache;
873
- };
874
997
  /**
875
- * Create a fetch wrapper that handles x402 payment automatically.
998
+ * Wallet Key Derivation
876
999
  *
877
- * Supports pre-auth: if cached payment params + estimated amount are available,
878
- * pre-signs and attaches payment to the first request, skipping the 402 round trip.
879
- * Falls back to normal 402 flow if pre-signed payment is rejected.
1000
+ * BIP-39 mnemonic generation + BIP-44 HD key derivation for EVM and Solana.
1001
+ * Absorbed from @blockrun/clawwallet. No file I/O here - auth.ts handles persistence.
1002
+ */
1003
+ interface DerivedKeys {
1004
+ mnemonic: string;
1005
+ evmPrivateKey: `0x${string}`;
1006
+ evmAddress: string;
1007
+ solanaPrivateKeyBytes: Uint8Array;
1008
+ }
1009
+ /**
1010
+ * Generate a 24-word BIP-39 mnemonic.
1011
+ */
1012
+ declare function generateWalletMnemonic(): string;
1013
+ /**
1014
+ * Validate a BIP-39 mnemonic.
1015
+ */
1016
+ declare function isValidMnemonic(mnemonic: string): boolean;
1017
+ /**
1018
+ * Derive EVM private key and address from a BIP-39 mnemonic.
1019
+ * Path: m/44'/60'/0'/0/0 (standard Ethereum derivation)
1020
+ */
1021
+ declare function deriveEvmKey(mnemonic: string): {
1022
+ privateKey: `0x${string}`;
1023
+ address: string;
1024
+ };
1025
+ /**
1026
+ * Derive 32-byte Solana private key from a BIP-39 mnemonic.
1027
+ * Path: m/44'/501'/0'/0' (standard Solana derivation)
1028
+ */
1029
+ declare function deriveSolanaKeyBytes(mnemonic: string): Uint8Array;
1030
+ /**
1031
+ * Derive both EVM and Solana keys from a single mnemonic.
880
1032
  */
881
- declare function createPaymentFetch(privateKey: `0x${string}`): PaymentFetchResult;
1033
+ declare function deriveAllKeys(mnemonic: string): DerivedKeys;
882
1034
 
883
1035
  /**
884
1036
  * Typed Error Classes for ClawRouter
@@ -1125,4 +1277,4 @@ declare function buildPartnerTools(proxyBaseUrl: string): PartnerToolDefinition[
1125
1277
 
1126
1278
  declare const plugin: OpenClawPluginDefinition;
1127
1279
 
1128
- export { type AggregatedStats, BALANCE_THRESHOLDS, BLOCKRUN_MODELS, type BalanceInfo, BalanceMonitor, type CachedLLMResponse, type CachedPaymentParams, type CachedResponse, DEFAULT_RETRY_CONFIG, DEFAULT_ROUTING_CONFIG, DEFAULT_SESSION_CONFIG, type DailyStats, EmptyWalletError, InsufficientFundsError, type InsufficientFundsInfo, type LowBalanceInfo, MODEL_ALIASES, OPENCLAW_MODELS, PARTNER_SERVICES, type PartnerServiceDefinition, type PartnerToolDefinition, PaymentCache, type PaymentFetchResult, type PreAuthParams, type ProxyHandle, type ProxyOptions, RequestDeduplicator, ResponseCache, type ResponseCacheConfig, type RetryConfig, type RoutingConfig, type RoutingDecision, RpcError, type SessionConfig, type SessionEntry, SessionStore, type SufficiencyResult, type Tier, type UsageEntry, blockrunProvider, buildPartnerTools, buildProviderModels, calculateModelCost, createPaymentFetch, plugin as default, fetchWithRetry, formatStatsAscii, getAgenticModels, getFallbackChain, getFallbackChainFiltered, getModelContextWindow, getPartnerService, getProxyPort, getSessionId, getStats, hashRequestContent, isAgenticModel, isBalanceError, isEmptyWalletError, isInsufficientFundsError, isRetryable, isRpcError, logUsage, resolveModelAlias, route, startProxy };
1280
+ export { type AggregatedStats, BALANCE_THRESHOLDS, BLOCKRUN_MODELS, type BalanceInfo, BalanceMonitor, type CachedLLMResponse, type CachedResponse, type CheckResult, DEFAULT_RETRY_CONFIG, DEFAULT_ROUTING_CONFIG, DEFAULT_SESSION_CONFIG, type DailyStats, type DerivedKeys, EmptyWalletError, FileSpendControlStorage, InMemorySpendControlStorage, InsufficientFundsError, type InsufficientFundsInfo, type LowBalanceInfo, MODEL_ALIASES, OPENCLAW_MODELS, PARTNER_SERVICES, type PartnerServiceDefinition, type PartnerToolDefinition, type PaymentChain, type ProxyHandle, type ProxyOptions, RequestDeduplicator, ResponseCache, type ResponseCacheConfig, type RetryConfig, type RoutingConfig, type RoutingDecision, RpcError, type SessionConfig, type SessionEntry, SessionStore, type SolanaBalanceInfo, SolanaBalanceMonitor, SpendControl, type SpendControlOptions, type SpendControlStorage, type SpendLimits, type SpendRecord, type SpendWindow, type SpendingStatus, type SufficiencyResult, type Tier, type UsageEntry, type WalletConfig, type WalletResolution, blockrunProvider, buildPartnerTools, buildProviderModels, calculateModelCost, plugin as default, deriveAllKeys, deriveEvmKey, deriveSolanaKeyBytes, fetchWithRetry, formatDuration, formatStatsAscii, generateWalletMnemonic, getAgenticModels, getFallbackChain, getFallbackChainFiltered, getModelContextWindow, getPartnerService, getProxyPort, getSessionId, getStats, isAgenticModel, isBalanceError, isEmptyWalletError, isInsufficientFundsError, isRetryable, isRpcError, isValidMnemonic, loadPaymentChain, logUsage, resolveModelAlias, resolvePaymentChain, route, savePaymentChain, setupSolana, startProxy };