@blockrun/clawrouter 0.4.7 → 0.5.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BlockRunAI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,8 +1,6 @@
1
- <div align="center">
2
-
3
- # ClawRouter
1
+ ![ClawRouter Banner](assets/banner.png)
4
2
 
5
- **Save 78% on LLM costs. Automatically.**
3
+ <div align="center">
6
4
 
7
5
  Route every request to the cheapest model that can handle it.
8
6
  One wallet, 30+ models, zero API keys.
@@ -28,7 +26,7 @@ One wallet, 30+ models, zero API keys.
28
26
 
29
27
  ## Why ClawRouter?
30
28
 
31
- - **100% local routing** — 14-dimension weighted scoring runs on your machine in <1ms
29
+ - **100% local routing** — 15-dimension weighted scoring runs on your machine in <1ms
32
30
  - **Zero external calls** — no API calls for routing decisions, ever
33
31
  - **30+ models** — OpenAI, Anthropic, Google, DeepSeek, xAI, Moonshot through one wallet
34
32
  - **x402 micropayments** — pay per request with USDC on Base, no API keys
@@ -94,14 +92,14 @@ Request → Weighted Scorer (14 dimensions)
94
92
 
95
93
  No external classifier calls. Ambiguous queries default to the MEDIUM tier (DeepSeek/GPT-4o-mini) — fast, cheap, and good enough for most tasks.
96
94
 
97
- ### 14-Dimension Weighted Scoring
95
+ ### 15-Dimension Weighted Scoring
98
96
 
99
97
  | Dimension | Weight | What It Detects |
100
98
  | -------------------- | ------ | ---------------------------------------- |
101
99
  | Reasoning markers | 0.18 | "prove", "theorem", "step by step" |
102
100
  | Code presence | 0.15 | "function", "async", "import", "```" |
103
- | Simple indicators | 0.12 | "what is", "define", "translate" |
104
101
  | Multi-step patterns | 0.12 | "first...then", "step 1", numbered lists |
102
+ | **Agentic task** | 0.10 | "run", "test", "fix", "deploy", "edit" |
105
103
  | Technical terms | 0.10 | "algorithm", "kubernetes", "distributed" |
106
104
  | Token count | 0.08 | short (<50) vs long (>500) prompts |
107
105
  | Creative markers | 0.05 | "story", "poem", "brainstorm" |
@@ -109,6 +107,7 @@ No external classifier calls. Ambiguous queries default to the MEDIUM tier (Deep
109
107
  | Constraint count | 0.04 | "at most", "O(n)", "maximum" |
110
108
  | Imperative verbs | 0.03 | "build", "create", "implement" |
111
109
  | Output format | 0.03 | "json", "yaml", "schema" |
110
+ | Simple indicators | 0.02 | "what is", "define", "translate" |
112
111
  | Domain specificity | 0.02 | "quantum", "fpga", "genomics" |
113
112
  | Reference complexity | 0.02 | "the docs", "the api", "above" |
114
113
  | Negation complexity | 0.01 | "don't", "avoid", "without" |
@@ -131,15 +130,94 @@ Mixed-language prompts are supported — keywords from all languages are checked
131
130
 
132
131
  ### Tier → Model Mapping
133
132
 
134
- | Tier | Primary Model | Cost/M | Savings vs Opus |
135
- | --------- | ----------------- | ------ | --------------- |
136
- | SIMPLE | gemini-2.5-flash | $0.60 | **99.2%** |
137
- | MEDIUM | deepseek-chat | $0.42 | **99.4%** |
138
- | COMPLEX | claude-opus-4 | $75.00 | baseline |
139
- | REASONING | deepseek-reasoner | $0.42 | **99.4%** |
133
+ | Tier | Primary Model | Cost/M | Savings vs Opus |
134
+ | --------- | --------------------- | ------ | --------------- |
135
+ | SIMPLE | gemini-2.5-flash | $0.60 | **99.2%** |
136
+ | MEDIUM | grok-code-fast-1 | $1.50 | **98.0%** |
137
+ | COMPLEX | gemini-2.5-pro | $10.00 | **86.7%** |
138
+ | REASONING | grok-4-fast-reasoning | $0.50 | **99.3%** |
140
139
 
141
140
  Special rule: 2+ reasoning markers → REASONING at 0.97 confidence.
142
141
 
142
+ ### Agentic Auto-Detection
143
+
144
+ ClawRouter automatically detects multi-step agentic tasks and routes to models optimized for autonomous execution:
145
+
146
+ ```
147
+ "what is 2+2" → gemini-flash (standard)
148
+ "build the project then run tests" → kimi-k2.5 (auto-agentic)
149
+ "fix the bug and make sure it works" → kimi-k2.5 (auto-agentic)
150
+ ```
151
+
152
+ **How it works:**
153
+
154
+ - Detects agentic keywords: file ops ("read", "edit"), execution ("run", "test", "deploy"), iteration ("fix", "debug", "verify")
155
+ - Threshold: 2+ signals triggers auto-switch to agentic tiers
156
+ - No config needed — works automatically
157
+
158
+ **Agentic tier models** (optimized for multi-step autonomy):
159
+
160
+ | Tier | Agentic Model | Why |
161
+ | --------- | ---------------- | ------------------------------ |
162
+ | SIMPLE | claude-haiku-4.5 | Fast + reliable tool use |
163
+ | MEDIUM | kimi-k2.5 | 200+ tool chains, 76% cheaper |
164
+ | COMPLEX | claude-sonnet-4 | Best balance for complex tasks |
165
+ | REASONING | kimi-k2.5 | Extended reasoning + execution |
166
+
167
+ You can also force agentic mode via config:
168
+
169
+ ```yaml
170
+ # openclaw.yaml
171
+ plugins:
172
+ - id: "@blockrun/clawrouter"
173
+ config:
174
+ routing:
175
+ overrides:
176
+ agenticMode: true # Always use agentic tiers
177
+ ```
178
+
179
+ ### Tool Detection (v0.5)
180
+
181
+ When your request includes a `tools` array (function calling), ClawRouter automatically switches to agentic tiers:
182
+
183
+ ```typescript
184
+ // Request with tools → auto-agentic mode
185
+ {
186
+ model: "blockrun/auto",
187
+ messages: [{ role: "user", content: "Check the weather" }],
188
+ tools: [{ type: "function", function: { name: "get_weather", ... } }]
189
+ }
190
+ // → Routes to claude-haiku-4.5 (excellent tool use)
191
+ // → Instead of gemini-flash (may produce malformed tool calls)
192
+ ```
193
+
194
+ **Why this matters:** Some models (like `deepseek-reasoner`) are optimized for chain-of-thought reasoning but can generate malformed tool calls. Tool detection ensures requests with functions go to models proven to handle tool use correctly.
195
+
196
+ ### Context-Length-Aware Routing (v0.5)
197
+
198
+ ClawRouter automatically filters out models that can't handle your context size:
199
+
200
+ ```
201
+ 150K token request:
202
+ Full chain: [grok-4-fast (131K), deepseek (128K), kimi (262K), gemini (1M)]
203
+ Filtered: [kimi (262K), gemini (1M)]
204
+ → Skips models that would fail with "context too long" errors
205
+ ```
206
+
207
+ This prevents wasted API calls and faster fallback to capable models.
208
+
209
+ ### Session Persistence (v0.5)
210
+
211
+ For multi-turn conversations, ClawRouter pins the model to prevent mid-task switching:
212
+
213
+ ```
214
+ Turn 1: "Build a React component" → claude-sonnet-4
215
+ Turn 2: "Add dark mode support" → claude-sonnet-4 (pinned)
216
+ Turn 3: "Now add tests" → claude-sonnet-4 (pinned)
217
+ ```
218
+
219
+ Sessions are identified by conversation ID and persist for 1 hour of inactivity.
220
+
143
221
  ### Cost Savings (Real Numbers)
144
222
 
145
223
  | Tier | % of Traffic | Cost/M |
@@ -158,29 +236,34 @@ Compared to **$75/M** for Claude Opus = **96% savings** on a typical workload.
158
236
 
159
237
  30+ models across 6 providers, one wallet:
160
238
 
161
- | Model | Input $/M | Output $/M | Context | Reasoning |
162
- | ----------------- | --------- | ---------- | ------- | :-------: |
163
- | **OpenAI** | | | | |
164
- | gpt-5.2 | $1.75 | $14.00 | 400K | \* |
165
- | gpt-4o | $2.50 | $10.00 | 128K | |
166
- | gpt-4o-mini | $0.15 | $0.60 | 128K | |
167
- | o3 | $2.00 | $8.00 | 200K | \* |
168
- | o3-mini | $1.10 | $4.40 | 128K | \* |
169
- | **Anthropic** | | | | |
170
- | claude-opus-4.5 | $5.00 | $25.00 | 200K | \* |
171
- | claude-sonnet-4 | $3.00 | $15.00 | 200K | \* |
172
- | claude-haiku-4.5 | $1.00 | $5.00 | 200K | |
173
- | **Google** | | | | |
174
- | gemini-2.5-pro | $1.25 | $10.00 | 1M | \* |
175
- | gemini-2.5-flash | $0.15 | $0.60 | 1M | |
176
- | **DeepSeek** | | | | |
177
- | deepseek-chat | $0.14 | $0.28 | 128K | |
178
- | deepseek-reasoner | $0.55 | $2.19 | 128K | \* |
179
- | **xAI** | | | | |
180
- | grok-3 | $3.00 | $15.00 | 131K | \* |
181
- | grok-3-mini | $0.30 | $0.50 | 131K | |
182
- | **Moonshot** | | | | |
183
- | kimi-k2.5 | $0.50 | $2.40 | 128K | \* |
239
+ | Model | Input $/M | Output $/M | Context | Reasoning |
240
+ | --------------------- | --------- | ---------- | ------- | :-------: |
241
+ | **OpenAI** | | | | |
242
+ | gpt-5.2 | $1.75 | $14.00 | 400K | \* |
243
+ | gpt-4o | $2.50 | $10.00 | 128K | |
244
+ | gpt-4o-mini | $0.15 | $0.60 | 128K | |
245
+ | o3 | $2.00 | $8.00 | 200K | \* |
246
+ | o3-mini | $1.10 | $4.40 | 128K | \* |
247
+ | **Anthropic** | | | | |
248
+ | claude-opus-4.5 | $5.00 | $25.00 | 200K | \* |
249
+ | claude-sonnet-4 | $3.00 | $15.00 | 200K | \* |
250
+ | claude-haiku-4.5 | $1.00 | $5.00 | 200K | |
251
+ | **Google** | | | | |
252
+ | gemini-2.5-pro | $1.25 | $10.00 | 1M | \* |
253
+ | gemini-2.5-flash | $0.15 | $0.60 | 1M | |
254
+ | **DeepSeek** | | | | |
255
+ | deepseek-chat | $0.14 | $0.28 | 128K | |
256
+ | deepseek-reasoner | $0.55 | $2.19 | 128K | \* |
257
+ | **xAI** | | | | |
258
+ | grok-3 | $3.00 | $15.00 | 131K | \* |
259
+ | grok-3-mini | $0.30 | $0.50 | 131K | |
260
+ | grok-4-fast-reasoning | $0.20 | $0.50 | 131K | \* |
261
+ | grok-4-fast | $0.20 | $0.50 | 131K | |
262
+ | grok-code-fast-1 | $0.20 | $1.50 | 131K | |
263
+ | **Moonshot** | | | | |
264
+ | kimi-k2.5 | $0.50 | $2.40 | 262K | \* |
265
+ | **NVIDIA** | | | | |
266
+ | gpt-oss-120b | **FREE** | **FREE** | 128K | |
184
267
 
185
268
  Full list: [`src/models.ts`](src/models.ts)
186
269
 
@@ -446,6 +529,39 @@ console.log(decision);
446
529
 
447
530
  ---
448
531
 
532
+ ## Cost Tracking with /stats (v0.5)
533
+
534
+ Track your savings in real-time:
535
+
536
+ ```bash
537
+ # In any OpenClaw conversation
538
+ /stats
539
+ ```
540
+
541
+ Output:
542
+
543
+ ```
544
+ ╔════════════════════════════════════════════════════════════╗
545
+ ║ ClawRouter Usage Statistics ║
546
+ ╠════════════════════════════════════════════════════════════╣
547
+ ║ Period: last 7 days ║
548
+ ║ Total Requests: 442 ║
549
+ ║ Total Cost: $1.73 ║
550
+ ║ Baseline Cost (Opus): $20.13 ║
551
+ ║ 💰 Total Saved: $18.40 (91.4%) ║
552
+ ╠════════════════════════════════════════════════════════════╣
553
+ ║ Routing by Tier: ║
554
+ ║ SIMPLE ███████████ 55.0% (243) ║
555
+ ║ MEDIUM ██████ 30.8% (136) ║
556
+ ║ COMPLEX █ 7.2% (32) ║
557
+ ║ REASONING █ 7.0% (31) ║
558
+ ╚════════════════════════════════════════════════════════════╝
559
+ ```
560
+
561
+ Stats are stored locally at `~/.openclaw/blockrun/logs/` and aggregated on demand.
562
+
563
+ ---
564
+
449
565
  ## Why Not OpenRouter / LiteLLM?
450
566
 
451
567
  They're built for developers. ClawRouter is built for **agents**.
@@ -468,7 +584,7 @@ Agents shouldn't need a human to paste API keys. They should generate a wallet,
468
584
  ### Quick Checklist
469
585
 
470
586
  ```bash
471
- # 1. Check your version (should be 0.3.21+)
587
+ # 1. Check your version (should be 0.5.0+)
472
588
  cat ~/.openclaw/extensions/clawrouter/package.json | grep version
473
589
 
474
590
  # 2. Check proxy is running
@@ -477,6 +593,9 @@ curl http://localhost:8402/health
477
593
  # 3. Watch routing in action
478
594
  openclaw logs --follow
479
595
  # Should see: gemini-2.5-flash $0.0012 (saved 99%)
596
+
597
+ # 4. View cost savings
598
+ /stats
480
599
  ```
481
600
 
482
601
  ### "Unknown model: blockrun/auto" or "Unknown model: auto"
@@ -508,6 +627,15 @@ Wallet needs funding.
508
627
  3. $1-5 is enough for hundreds of requests
509
628
  4. Restart OpenClaw
510
629
 
630
+ ### "WARNING: dangerous code patterns — possible credential harvesting"
631
+
632
+ This is a **false positive**. ClawRouter legitimately:
633
+
634
+ 1. Reads `BLOCKRUN_WALLET_KEY` from environment (for authentication)
635
+ 2. Sends authenticated requests to BlockRun API (for x402 micropayments)
636
+
637
+ This pattern triggers OpenClaw's security scanner, but it's the intended behavior — the wallet key is required to sign payment transactions. The code is fully open source and auditable.
638
+
511
639
  ### Security Scanner Warning: "env-harvesting"
512
640
 
513
641
  OpenClaw's security scanner may flag ClawRouter with:
@@ -586,14 +714,19 @@ BLOCKRUN_WALLET_KEY=0x... npx tsx test-e2e.ts
586
714
 
587
715
  ## Roadmap
588
716
 
589
- - [x] Smart routing — 14-dimension weighted scoring, 4-tier model selection
717
+ - [x] Smart routing — 15-dimension weighted scoring, 4-tier model selection
590
718
  - [x] x402 payments — per-request USDC micropayments, non-custodial
591
719
  - [x] Response dedup — prevents double-charge on retries
592
720
  - [x] Payment pre-auth — skips 402 round trip
593
721
  - [x] SSE heartbeat — prevents upstream timeouts
722
+ - [x] Agentic auto-detect — auto-switch to agentic models for multi-step tasks
723
+ - [x] Tool detection — auto-switch to agentic mode when tools array present
724
+ - [x] Context-aware routing — filter out models that can't handle context size
725
+ - [x] Session persistence — pin model for multi-turn conversations
726
+ - [x] Cost tracking — /stats command with savings dashboard
594
727
  - [ ] Cascade routing — try cheap model first, escalate on low quality
595
728
  - [ ] Spend controls — daily/monthly budgets
596
- - [ ] Analytics dashboard — cost tracking at blockrun.ai
729
+ - [ ] Remote analytics — cost tracking at blockrun.ai
597
730
 
598
731
  ---
599
732
 
package/dist/index.d.ts CHANGED
@@ -168,6 +168,7 @@ type ScoringConfig = {
168
168
  referenceKeywords: string[];
169
169
  negationKeywords: string[];
170
170
  domainSpecificKeywords: string[];
171
+ agenticTaskKeywords: string[];
171
172
  dimensionWeights: Record<string, number>;
172
173
  tierBoundaries: {
173
174
  simpleMedium: number;
@@ -188,12 +189,20 @@ type OverridesConfig = {
188
189
  maxTokensForceComplex: number;
189
190
  structuredOutputMinTier: Tier;
190
191
  ambiguousDefaultTier: Tier;
192
+ /**
193
+ * When enabled, prefer models optimized for agentic workflows.
194
+ * Agentic models continue autonomously with multi-step tasks
195
+ * instead of stopping and waiting for user input.
196
+ */
197
+ agenticMode?: boolean;
191
198
  };
192
199
  type RoutingConfig = {
193
200
  version: string;
194
201
  classifier: ClassifierConfig;
195
202
  scoring: ScoringConfig;
196
203
  tiers: Record<Tier, TierConfig>;
204
+ /** Tier configs for agentic mode - models that excel at multi-step tasks */
205
+ agenticTiers?: Record<Tier, TierConfig>;
197
206
  overrides: OverridesConfig;
198
207
  };
199
208
 
@@ -208,6 +217,21 @@ type ModelPricing = {
208
217
  inputPrice: number;
209
218
  outputPrice: number;
210
219
  };
220
+ /**
221
+ * Get the ordered fallback chain for a tier: [primary, ...fallbacks].
222
+ */
223
+ declare function getFallbackChain(tier: Tier, tierConfigs: Record<Tier, TierConfig>): string[];
224
+ /**
225
+ * Get the fallback chain filtered by context length.
226
+ * Only returns models that can handle the estimated total context.
227
+ *
228
+ * @param tier - The tier to get fallback chain for
229
+ * @param tierConfigs - Tier configurations
230
+ * @param estimatedTotalTokens - Estimated total context (input + output)
231
+ * @param getContextWindow - Function to get context window for a model ID
232
+ * @returns Filtered list of models that can handle the context
233
+ */
234
+ declare function getFallbackChainFiltered(tier: Tier, tierConfigs: Record<Tier, TierConfig>, estimatedTotalTokens: number, getContextWindow: (modelId: string) => number | undefined): string[];
211
235
 
212
236
  /**
213
237
  * Default Routing Config
@@ -340,6 +364,82 @@ declare class BalanceMonitor {
340
364
  private buildInfo;
341
365
  }
342
366
 
367
+ /**
368
+ * Session Persistence Store
369
+ *
370
+ * Tracks model selections per session to prevent model switching mid-task.
371
+ * When a session is active, the router will continue using the same model
372
+ * instead of re-routing each request.
373
+ */
374
+ type SessionEntry = {
375
+ model: string;
376
+ tier: string;
377
+ createdAt: number;
378
+ lastUsedAt: number;
379
+ requestCount: number;
380
+ };
381
+ type SessionConfig = {
382
+ /** Enable session persistence (default: false) */
383
+ enabled: boolean;
384
+ /** Session timeout in ms (default: 30 minutes) */
385
+ timeoutMs: number;
386
+ /** Header name for session ID (default: X-Session-ID) */
387
+ headerName: string;
388
+ };
389
+ declare const DEFAULT_SESSION_CONFIG: SessionConfig;
390
+ /**
391
+ * Session persistence store for maintaining model selections.
392
+ */
393
+ declare class SessionStore {
394
+ private sessions;
395
+ private config;
396
+ private cleanupInterval;
397
+ constructor(config?: Partial<SessionConfig>);
398
+ /**
399
+ * Get the pinned model for a session, if any.
400
+ */
401
+ getSession(sessionId: string): SessionEntry | undefined;
402
+ /**
403
+ * Pin a model to a session.
404
+ */
405
+ setSession(sessionId: string, model: string, tier: string): void;
406
+ /**
407
+ * Touch a session to extend its timeout.
408
+ */
409
+ touchSession(sessionId: string): void;
410
+ /**
411
+ * Clear a specific session.
412
+ */
413
+ clearSession(sessionId: string): void;
414
+ /**
415
+ * Clear all sessions.
416
+ */
417
+ clearAll(): void;
418
+ /**
419
+ * Get session stats for debugging.
420
+ */
421
+ getStats(): {
422
+ count: number;
423
+ sessions: Array<{
424
+ id: string;
425
+ model: string;
426
+ age: number;
427
+ }>;
428
+ };
429
+ /**
430
+ * Clean up expired sessions.
431
+ */
432
+ private cleanup;
433
+ /**
434
+ * Stop the cleanup interval.
435
+ */
436
+ close(): void;
437
+ }
438
+ /**
439
+ * Generate a session ID from request headers or create a default.
440
+ */
441
+ declare function getSessionId(headers: Record<string, string | string[] | undefined>, headerName?: string): string | undefined;
442
+
343
443
  /**
344
444
  * Local x402 Proxy Server
345
445
  *
@@ -388,6 +488,11 @@ type ProxyOptions = {
388
488
  requestTimeoutMs?: number;
389
489
  /** Skip balance checks (for testing only). Default: false */
390
490
  skipBalanceCheck?: boolean;
491
+ /**
492
+ * Session persistence config. When enabled, maintains model selection
493
+ * across requests within a session to prevent mid-task model switching.
494
+ */
495
+ sessionConfig?: Partial<SessionConfig>;
391
496
  onReady?: (port: number) => void;
392
497
  onError?: (error: Error) => void;
393
498
  onPayment?: (info: {
@@ -441,6 +546,16 @@ declare const blockrunProvider: ProviderPlugin;
441
546
  * they set their own markup when reselling to end users (Phase 2).
442
547
  */
443
548
 
549
+ /**
550
+ * Model aliases for convenient shorthand access.
551
+ * Users can type `/model claude` instead of `/model blockrun/anthropic/claude-sonnet-4`.
552
+ */
553
+ declare const MODEL_ALIASES: Record<string, string>;
554
+ /**
555
+ * Resolve a model alias to its full model ID.
556
+ * Returns the original model if not an alias.
557
+ */
558
+ declare function resolveModelAlias(model: string): string;
444
559
  type BlockRunModel = {
445
560
  id: string;
446
561
  name: string;
@@ -450,6 +565,8 @@ type BlockRunModel = {
450
565
  maxOutput: number;
451
566
  reasoning?: boolean;
452
567
  vision?: boolean;
568
+ /** Models optimized for agentic workflows (multi-step autonomous tasks) */
569
+ agentic?: boolean;
453
570
  };
454
571
  declare const BLOCKRUN_MODELS: BlockRunModel[];
455
572
  /**
@@ -462,6 +579,21 @@ declare const OPENCLAW_MODELS: ModelDefinitionConfig[];
462
579
  * @param baseUrl - The proxy's local base URL (e.g., "http://127.0.0.1:12345")
463
580
  */
464
581
  declare function buildProviderModels(baseUrl: string): ModelProviderConfig;
582
+ /**
583
+ * Check if a model is optimized for agentic workflows.
584
+ * Agentic models continue autonomously with multi-step tasks
585
+ * instead of stopping and waiting for user input.
586
+ */
587
+ declare function isAgenticModel(modelId: string): boolean;
588
+ /**
589
+ * Get all agentic-capable models.
590
+ */
591
+ declare function getAgenticModels(): string[];
592
+ /**
593
+ * Get context window size for a model.
594
+ * Returns undefined if model not found.
595
+ */
596
+ declare function getModelContextWindow(modelId: string): number | undefined;
465
597
 
466
598
  /**
467
599
  * Usage Logger
@@ -475,7 +607,10 @@ declare function buildProviderModels(baseUrl: string): ModelProviderConfig;
475
607
  type UsageEntry = {
476
608
  timestamp: string;
477
609
  model: string;
610
+ tier: string;
478
611
  cost: number;
612
+ baselineCost: number;
613
+ savings: number;
479
614
  latencyMs: number;
480
615
  };
481
616
  /**
@@ -674,6 +809,58 @@ declare function fetchWithRetry(fetchFn: (url: string, init?: RequestInit) => Pr
674
809
  */
675
810
  declare function isRetryable(errorOrResponse: Error | Response, config?: Partial<RetryConfig>): boolean;
676
811
 
812
+ /**
813
+ * Usage Statistics Aggregator
814
+ *
815
+ * Reads usage log files and aggregates statistics for terminal display.
816
+ * Supports filtering by date range and provides multiple aggregation views.
817
+ */
818
+ type DailyStats = {
819
+ date: string;
820
+ totalRequests: number;
821
+ totalCost: number;
822
+ totalBaselineCost: number;
823
+ totalSavings: number;
824
+ avgLatencyMs: number;
825
+ byTier: Record<string, {
826
+ count: number;
827
+ cost: number;
828
+ }>;
829
+ byModel: Record<string, {
830
+ count: number;
831
+ cost: number;
832
+ }>;
833
+ };
834
+ type AggregatedStats = {
835
+ period: string;
836
+ totalRequests: number;
837
+ totalCost: number;
838
+ totalBaselineCost: number;
839
+ totalSavings: number;
840
+ savingsPercentage: number;
841
+ avgLatencyMs: number;
842
+ avgCostPerRequest: number;
843
+ byTier: Record<string, {
844
+ count: number;
845
+ cost: number;
846
+ percentage: number;
847
+ }>;
848
+ byModel: Record<string, {
849
+ count: number;
850
+ cost: number;
851
+ percentage: number;
852
+ }>;
853
+ dailyBreakdown: DailyStats[];
854
+ };
855
+ /**
856
+ * Get aggregated statistics for the last N days.
857
+ */
858
+ declare function getStats(days?: number): Promise<AggregatedStats>;
859
+ /**
860
+ * Format stats as ASCII table for terminal display.
861
+ */
862
+ declare function formatStatsAscii(stats: AggregatedStats): string;
863
+
677
864
  /**
678
865
  * @blockrun/clawrouter
679
866
  *
@@ -695,4 +882,4 @@ declare function isRetryable(errorOrResponse: Error | Response, config?: Partial
695
882
 
696
883
  declare const plugin: OpenClawPluginDefinition;
697
884
 
698
- export { BALANCE_THRESHOLDS, BLOCKRUN_MODELS, type BalanceInfo, BalanceMonitor, type CachedPaymentParams, type CachedResponse, DEFAULT_RETRY_CONFIG, DEFAULT_ROUTING_CONFIG, EmptyWalletError, InsufficientFundsError, type InsufficientFundsInfo, type LowBalanceInfo, OPENCLAW_MODELS, PaymentCache, type PaymentFetchResult, type PreAuthParams, type ProxyHandle, type ProxyOptions, RequestDeduplicator, type RetryConfig, type RoutingConfig, type RoutingDecision, RpcError, type SufficiencyResult, type Tier, type UsageEntry, blockrunProvider, buildProviderModels, createPaymentFetch, plugin as default, fetchWithRetry, getProxyPort, isBalanceError, isEmptyWalletError, isInsufficientFundsError, isRetryable, isRpcError, logUsage, route, startProxy };
885
+ export { type AggregatedStats, BALANCE_THRESHOLDS, BLOCKRUN_MODELS, type BalanceInfo, BalanceMonitor, 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, PaymentCache, type PaymentFetchResult, type PreAuthParams, type ProxyHandle, type ProxyOptions, RequestDeduplicator, type RetryConfig, type RoutingConfig, type RoutingDecision, RpcError, type SessionConfig, type SessionEntry, SessionStore, type SufficiencyResult, type Tier, type UsageEntry, blockrunProvider, buildProviderModels, createPaymentFetch, plugin as default, fetchWithRetry, formatStatsAscii, getAgenticModels, getFallbackChain, getFallbackChainFiltered, getModelContextWindow, getProxyPort, getSessionId, getStats, isAgenticModel, isBalanceError, isEmptyWalletError, isInsufficientFundsError, isRetryable, isRpcError, logUsage, resolveModelAlias, route, startProxy };