@blockrun/clawrouter 0.10.0 → 0.10.2

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
@@ -33,17 +33,18 @@ One wallet, 38+ models, zero API keys.
33
33
 
34
34
  ## 📑 Quick Navigation
35
35
 
36
- | Section | Description |
37
- | ----------------------------------------- | --------------------------- |
38
- | [Quick Start](#-quick-start) | Install in 2 minutes |
39
- | [Routing Profiles](#-routing-profiles) | eco / auto / premium / free |
40
- | [How It Works](#-how-it-works) | 15-dimension local routing |
41
- | [Models & Pricing](#-models--pricing) | 30+ models, full price list |
42
- | [Screenshots](#-screenshots) | See it in action |
43
- | [Payment](#-payment) | x402 non-custodial USDC |
44
- | [Configuration](#%EF%B8%8F-configuration) | Environment variables |
45
- | [vs OpenRouter](#-vs-openrouter) | Why ClawRouter wins |
46
- | [Support](#-support) | Telegram, X, founders |
36
+ | Section | Description |
37
+ | ----------------------------------------- | ------------------------------ |
38
+ | [Quick Start](#-quick-start) | Install in 2 minutes |
39
+ | [Routing Profiles](#-routing-profiles) | eco / auto / premium / free |
40
+ | [How It Works](#-how-it-works) | 15-dimension local routing |
41
+ | [Models & Pricing](#-models--pricing) | 30+ models, full price list |
42
+ | [Screenshots](#-screenshots) | See it in action |
43
+ | [Payment](#-payment) | x402 non-custodial USDC |
44
+ | [Configuration](#%EF%B8%8F-configuration) | Environment variables |
45
+ | [Troubleshooting](#-troubleshooting) | `doctor` AI-powered diagnostics |
46
+ | [vs OpenRouter](#-vs-openrouter) | Why ClawRouter wins |
47
+ | [Support](#-support) | Telegram, X, founders |
47
48
 
48
49
  ---
49
50
 
@@ -85,12 +86,12 @@ Choose your routing strategy with `/model <profile>`:
85
86
  Request → Weighted Scorer (15 dimensions) → Tier → Cheapest Model → Response
86
87
  ```
87
88
 
88
- | Tier | ECO Model | AUTO Model | PREMIUM Model |
89
- | --------- | ---------------------------------- | ---------------------------- | ---------------------------- |
90
- | SIMPLE | nvidia/gpt-oss-120b (FREE) | kimi-k2.5 ($0.60/$3.00) | kimi-k2.5 |
89
+ | Tier | ECO Model | AUTO Model | PREMIUM Model |
90
+ | --------- | ----------------------------------- | ---------------------------- | ---------------------------- |
91
+ | SIMPLE | nvidia/gpt-oss-120b (FREE) | kimi-k2.5 ($0.60/$3.00) | kimi-k2.5 |
91
92
  | MEDIUM | gemini-2.5-flash-lite ($0.10/$0.40) | grok-code-fast ($0.20/$1.50) | gpt-5.2-codex ($1.75/$14.00) |
92
93
  | COMPLEX | gemini-2.5-flash-lite ($0.10/$0.40) | gemini-3.1-pro ($2/$12) | claude-opus-4.6 ($5/$25) |
93
- | REASONING | grok-4-fast ($0.20/$0.50) | grok-4-fast ($0.20/$0.50) | claude-sonnet-4.6 ($3/$15) |
94
+ | REASONING | grok-4-fast ($0.20/$0.50) | grok-4-fast ($0.20/$0.50) | claude-sonnet-4.6 ($3/$15) |
94
95
 
95
96
  **Blended average: $2.05/M** vs $25/M for Claude Opus = **92% savings**
96
97
 
@@ -219,6 +220,48 @@ For basic usage, no configuration needed. For advanced options:
219
220
 
220
221
  ---
221
222
 
223
+ ## 🩺 Troubleshooting
224
+
225
+ **When things go wrong, run the doctor:**
226
+
227
+ ```bash
228
+ npx @blockrun/clawrouter doctor
229
+ ```
230
+
231
+ This collects diagnostics and sends them to Claude Opus 4.6 for AI-powered analysis:
232
+
233
+ ```
234
+ 🩺 BlockRun Doctor v0.10.1
235
+
236
+ System
237
+ ✓ OS: darwin arm64
238
+ ✓ Node: v20.11.0
239
+ ✓ Memory: 8.2GB free / 16.0GB
240
+
241
+ Wallet
242
+ ✓ Address: 0x1234...abcd
243
+ ✓ Balance: $12.50
244
+
245
+ Network
246
+ ✓ BlockRun API: reachable (142ms)
247
+ ✗ Local proxy: not running on :8402
248
+
249
+ 📤 Sending to Claude Opus 4.6...
250
+
251
+ 🤖 AI Analysis:
252
+ The local proxy isn't running. Run `openclaw gateway restart` to fix.
253
+ ```
254
+
255
+ **Ask a specific question:**
256
+
257
+ ```bash
258
+ npx @blockrun/clawrouter doctor "why is my request failing?"
259
+ ```
260
+
261
+ **Cost:** ~$0.01 per analysis (paid via your wallet balance)
262
+
263
+ ---
264
+
222
265
  ## 🛠 Development
223
266
 
224
267
  ```bash
package/dist/cli.js CHANGED
@@ -1277,7 +1277,11 @@ var DEFAULT_ROUTING_CONFIG = {
1277
1277
  SIMPLE: {
1278
1278
  primary: "moonshot/kimi-k2.5",
1279
1279
  // $0.60/$3.00 - good for simple coding
1280
- fallback: ["anthropic/claude-haiku-4.5", "google/gemini-2.5-flash-lite", "xai/grok-code-fast-1"]
1280
+ fallback: [
1281
+ "anthropic/claude-haiku-4.5",
1282
+ "google/gemini-2.5-flash-lite",
1283
+ "xai/grok-code-fast-1"
1284
+ ]
1281
1285
  },
1282
1286
  MEDIUM: {
1283
1287
  primary: "openai/gpt-5.2-codex",
@@ -1320,7 +1324,11 @@ var DEFAULT_ROUTING_CONFIG = {
1320
1324
  SIMPLE: {
1321
1325
  primary: "moonshot/kimi-k2.5",
1322
1326
  // Cheaper than Haiku ($0.5/$2.4 vs $1/$5), larger context
1323
- fallback: ["anthropic/claude-haiku-4.5", "xai/grok-4-1-fast-non-reasoning", "openai/gpt-4o-mini"]
1327
+ fallback: [
1328
+ "anthropic/claude-haiku-4.5",
1329
+ "xai/grok-4-1-fast-non-reasoning",
1330
+ "openai/gpt-4o-mini"
1331
+ ]
1324
1332
  },
1325
1333
  MEDIUM: {
1326
1334
  primary: "xai/grok-code-fast-1",
@@ -1342,7 +1350,11 @@ var DEFAULT_ROUTING_CONFIG = {
1342
1350
  REASONING: {
1343
1351
  primary: "anthropic/claude-sonnet-4.6",
1344
1352
  // Strong tool use + reasoning for agentic tasks
1345
- fallback: ["anthropic/claude-opus-4.6", "xai/grok-4-1-fast-reasoning", "deepseek/deepseek-reasoner"]
1353
+ fallback: [
1354
+ "anthropic/claude-opus-4.6",
1355
+ "xai/grok-4-1-fast-reasoning",
1356
+ "deepseek/deepseek-reasoner"
1357
+ ]
1346
1358
  }
1347
1359
  },
1348
1360
  overrides: {
@@ -4667,6 +4679,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
4667
4679
  } catch (err) {
4668
4680
  const errorMsg = err instanceof Error ? err.message : String(err);
4669
4681
  console.error(`[ClawRouter] Routing error: ${errorMsg}`);
4682
+ console.error(`[ClawRouter] Run 'npx @blockrun/clawrouter doctor' for help`);
4670
4683
  options.onError?.(new Error(`Routing failed: ${errorMsg}`));
4671
4684
  }
4672
4685
  }
@@ -5231,6 +5244,282 @@ async function resolveOrGenerateWalletKey() {
5231
5244
  return { key, address, source: "generated" };
5232
5245
  }
5233
5246
 
5247
+ // src/doctor.ts
5248
+ import { platform, arch, freemem, totalmem } from "os";
5249
+ function formatBytes(bytes) {
5250
+ const gb = bytes / (1024 * 1024 * 1024);
5251
+ return `${gb.toFixed(1)}GB`;
5252
+ }
5253
+ function green(text) {
5254
+ return `\x1B[32m\u2713\x1B[0m ${text}`;
5255
+ }
5256
+ function red(text) {
5257
+ return `\x1B[31m\u2717\x1B[0m ${text}`;
5258
+ }
5259
+ function yellow(text) {
5260
+ return `\x1B[33m\u26A0\x1B[0m ${text}`;
5261
+ }
5262
+ function collectSystemInfo() {
5263
+ return {
5264
+ os: `${platform()} ${arch()}`,
5265
+ arch: arch(),
5266
+ nodeVersion: process.version,
5267
+ memoryFree: formatBytes(freemem()),
5268
+ memoryTotal: formatBytes(totalmem())
5269
+ };
5270
+ }
5271
+ async function collectWalletInfo() {
5272
+ try {
5273
+ const { key, address, source } = await resolveOrGenerateWalletKey();
5274
+ if (!key || !address) {
5275
+ return {
5276
+ exists: false,
5277
+ valid: false,
5278
+ address: null,
5279
+ balance: null,
5280
+ isLow: false,
5281
+ isEmpty: true,
5282
+ source: null
5283
+ };
5284
+ }
5285
+ const monitor = new BalanceMonitor(address);
5286
+ try {
5287
+ const balanceInfo = await monitor.checkBalance();
5288
+ return {
5289
+ exists: true,
5290
+ valid: true,
5291
+ address,
5292
+ balance: balanceInfo.balanceUSD,
5293
+ isLow: balanceInfo.isLow,
5294
+ isEmpty: balanceInfo.isEmpty,
5295
+ source
5296
+ };
5297
+ } catch {
5298
+ return {
5299
+ exists: true,
5300
+ valid: true,
5301
+ address,
5302
+ balance: null,
5303
+ isLow: false,
5304
+ isEmpty: false,
5305
+ source
5306
+ };
5307
+ }
5308
+ } catch {
5309
+ return {
5310
+ exists: false,
5311
+ valid: false,
5312
+ address: null,
5313
+ balance: null,
5314
+ isLow: false,
5315
+ isEmpty: true,
5316
+ source: null
5317
+ };
5318
+ }
5319
+ }
5320
+ async function collectNetworkInfo() {
5321
+ const port = getProxyPort();
5322
+ let blockrunReachable = false;
5323
+ let blockrunLatency = null;
5324
+ try {
5325
+ const start = Date.now();
5326
+ const response = await fetch("https://blockrun.ai/api/v1/models", {
5327
+ method: "GET",
5328
+ signal: AbortSignal.timeout(1e4)
5329
+ });
5330
+ blockrunLatency = Date.now() - start;
5331
+ blockrunReachable = response.ok || response.status === 402;
5332
+ } catch {
5333
+ blockrunReachable = false;
5334
+ }
5335
+ let proxyRunning = false;
5336
+ try {
5337
+ const response = await fetch(`http://127.0.0.1:${port}/health`, {
5338
+ method: "GET",
5339
+ signal: AbortSignal.timeout(3e3)
5340
+ });
5341
+ proxyRunning = response.ok;
5342
+ } catch {
5343
+ proxyRunning = false;
5344
+ }
5345
+ return {
5346
+ blockrunApi: { reachable: blockrunReachable, latencyMs: blockrunLatency },
5347
+ localProxy: { running: proxyRunning, port }
5348
+ };
5349
+ }
5350
+ async function collectLogInfo() {
5351
+ try {
5352
+ const stats = await getStats(1);
5353
+ return {
5354
+ requestsLast24h: stats.totalRequests,
5355
+ costLast24h: `$${stats.totalCost.toFixed(4)}`,
5356
+ errorsFound: 0
5357
+ // TODO: parse error logs
5358
+ };
5359
+ } catch {
5360
+ return {
5361
+ requestsLast24h: 0,
5362
+ costLast24h: "$0.00",
5363
+ errorsFound: 0
5364
+ };
5365
+ }
5366
+ }
5367
+ function identifyIssues(result) {
5368
+ const issues = [];
5369
+ if (!result.wallet.exists) {
5370
+ issues.push("No wallet found");
5371
+ }
5372
+ if (result.wallet.isEmpty) {
5373
+ issues.push("Wallet is empty - need to fund with USDC on Base");
5374
+ } else if (result.wallet.isLow) {
5375
+ issues.push("Wallet balance is low (< $1.00)");
5376
+ }
5377
+ if (!result.network.blockrunApi.reachable) {
5378
+ issues.push("Cannot reach BlockRun API - check internet connection");
5379
+ }
5380
+ if (!result.network.localProxy.running) {
5381
+ issues.push(`Local proxy not running on port ${result.network.localProxy.port}`);
5382
+ }
5383
+ return issues;
5384
+ }
5385
+ function printDiagnostics(result) {
5386
+ console.log("\n\u{1F50D} Collecting diagnostics...\n");
5387
+ console.log("System");
5388
+ console.log(` ${green(`OS: ${result.system.os}`)}`);
5389
+ console.log(` ${green(`Node: ${result.system.nodeVersion}`)}`);
5390
+ console.log(` ${green(`Memory: ${result.system.memoryFree} free / ${result.system.memoryTotal}`)}`);
5391
+ console.log("\nWallet");
5392
+ if (result.wallet.exists && result.wallet.valid) {
5393
+ console.log(` ${green(`Key: ${WALLET_FILE} (${result.wallet.source})`)}`);
5394
+ console.log(` ${green(`Address: ${result.wallet.address}`)}`);
5395
+ if (result.wallet.isEmpty) {
5396
+ console.log(` ${red(`Balance: $0.00 - NEED TO FUND!`)}`);
5397
+ } else if (result.wallet.isLow) {
5398
+ console.log(` ${yellow(`Balance: ${result.wallet.balance} (low)`)}`);
5399
+ } else if (result.wallet.balance) {
5400
+ console.log(` ${green(`Balance: ${result.wallet.balance}`)}`);
5401
+ } else {
5402
+ console.log(` ${yellow(`Balance: checking...`)}`);
5403
+ }
5404
+ } else {
5405
+ console.log(` ${red("No wallet found")}`);
5406
+ }
5407
+ console.log("\nNetwork");
5408
+ if (result.network.blockrunApi.reachable) {
5409
+ console.log(` ${green(`BlockRun API: reachable (${result.network.blockrunApi.latencyMs}ms)`)}`);
5410
+ } else {
5411
+ console.log(` ${red("BlockRun API: unreachable")}`);
5412
+ }
5413
+ if (result.network.localProxy.running) {
5414
+ console.log(` ${green(`Local proxy: running on :${result.network.localProxy.port}`)}`);
5415
+ } else {
5416
+ console.log(` ${red(`Local proxy: not running on :${result.network.localProxy.port}`)}`);
5417
+ }
5418
+ console.log("\nLogs");
5419
+ console.log(` ${green(`Last 24h: ${result.logs.requestsLast24h} requests, ${result.logs.costLast24h} spent`)}`);
5420
+ if (result.logs.errorsFound > 0) {
5421
+ console.log(` ${yellow(`${result.logs.errorsFound} errors found in logs`)}`);
5422
+ }
5423
+ if (result.issues.length > 0) {
5424
+ console.log("\n\u26A0\uFE0F Issues Found:");
5425
+ for (const issue of result.issues) {
5426
+ console.log(` \u2022 ${issue}`);
5427
+ }
5428
+ }
5429
+ }
5430
+ async function analyzeWithAI(diagnostics, userQuestion) {
5431
+ if (diagnostics.wallet.isEmpty) {
5432
+ console.log("\n\u{1F4B3} Wallet is empty - cannot call AI for analysis.");
5433
+ console.log(` Fund your wallet with USDC on Base: ${diagnostics.wallet.address}`);
5434
+ console.log(" Get USDC: https://www.coinbase.com/price/usd-coin");
5435
+ console.log(" Bridge to Base: https://bridge.base.org\n");
5436
+ return;
5437
+ }
5438
+ console.log("\n\u{1F4E4} Sending to Claude Opus 4.6...\n");
5439
+ try {
5440
+ const { key } = await resolveOrGenerateWalletKey();
5441
+ const { fetch: paymentFetch } = createPaymentFetch(key);
5442
+ const response = await paymentFetch(
5443
+ "https://blockrun.ai/api/v1/chat/completions",
5444
+ {
5445
+ method: "POST",
5446
+ headers: { "Content-Type": "application/json" },
5447
+ body: JSON.stringify({
5448
+ model: "anthropic/claude-opus-4.6",
5449
+ stream: false,
5450
+ messages: [
5451
+ {
5452
+ role: "system",
5453
+ content: `You are a technical support expert for BlockRun and ClawRouter.
5454
+ Analyze the diagnostics and:
5455
+ 1. Identify the root cause of any issues
5456
+ 2. Provide specific, actionable fix commands (bash)
5457
+ 3. Explain why the issue occurred briefly
5458
+ 4. Be concise but thorough
5459
+ 5. Format commands in code blocks`
5460
+ },
5461
+ {
5462
+ role: "user",
5463
+ content: userQuestion ? `Here are my system diagnostics:
5464
+
5465
+ ${JSON.stringify(diagnostics, null, 2)}
5466
+
5467
+ User's question: ${userQuestion}` : `Here are my system diagnostics:
5468
+
5469
+ ${JSON.stringify(diagnostics, null, 2)}
5470
+
5471
+ Please analyze and help me fix any issues.`
5472
+ }
5473
+ ],
5474
+ max_tokens: 1e3
5475
+ })
5476
+ },
5477
+ void 0
5478
+ );
5479
+ if (!response.ok) {
5480
+ const text = await response.text();
5481
+ console.log(`Error: ${response.status} - ${text}`);
5482
+ return;
5483
+ }
5484
+ const data = await response.json();
5485
+ const content = data.choices?.[0]?.message?.content;
5486
+ if (content) {
5487
+ console.log("\u{1F916} AI Analysis:\n");
5488
+ console.log(content);
5489
+ console.log();
5490
+ } else {
5491
+ console.log("Error: No response from AI");
5492
+ }
5493
+ } catch (err) {
5494
+ console.log(`
5495
+ Error calling AI: ${err instanceof Error ? err.message : String(err)}`);
5496
+ console.log("Try again or check your wallet balance.\n");
5497
+ }
5498
+ }
5499
+ async function runDoctor(userQuestion) {
5500
+ console.log(`
5501
+ \u{1FA7A} BlockRun Doctor v${VERSION}
5502
+ `);
5503
+ const [system, wallet, network, logs] = await Promise.all([
5504
+ collectSystemInfo(),
5505
+ collectWalletInfo(),
5506
+ collectNetworkInfo(),
5507
+ collectLogInfo()
5508
+ ]);
5509
+ const result = {
5510
+ version: VERSION,
5511
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5512
+ system,
5513
+ wallet,
5514
+ network,
5515
+ logs,
5516
+ issues: []
5517
+ };
5518
+ result.issues = identifyIssues(result);
5519
+ printDiagnostics(result);
5520
+ await analyzeWithAI(result, userQuestion);
5521
+ }
5522
+
5234
5523
  // src/cli.ts
5235
5524
  function printHelp() {
5236
5525
  console.log(`
@@ -5238,12 +5527,17 @@ ClawRouter v${VERSION} - Smart LLM Router
5238
5527
 
5239
5528
  Usage:
5240
5529
  clawrouter [options]
5530
+ clawrouter doctor Run AI-powered diagnostics
5241
5531
 
5242
5532
  Options:
5243
5533
  --version, -v Show version number
5244
5534
  --help, -h Show this help message
5245
5535
  --port <number> Port to listen on (default: ${getProxyPort()})
5246
5536
 
5537
+ Commands:
5538
+ doctor [question] Diagnose issues and get AI-powered fix suggestions
5539
+ Optional: Add your question for targeted help
5540
+
5247
5541
  Examples:
5248
5542
  # Start standalone proxy (survives gateway restarts)
5249
5543
  npx @blockrun/clawrouter
@@ -5251,6 +5545,12 @@ Examples:
5251
5545
  # Start on custom port
5252
5546
  npx @blockrun/clawrouter --port 9000
5253
5547
 
5548
+ # Run diagnostics when something isn't working
5549
+ npx @blockrun/clawrouter doctor
5550
+
5551
+ # Ask a specific question
5552
+ npx @blockrun/clawrouter doctor "why is my request failing?"
5553
+
5254
5554
  # Production deployment with PM2
5255
5555
  pm2 start "npx @blockrun/clawrouter" --name clawrouter
5256
5556
 
@@ -5262,13 +5562,15 @@ For more info: https://github.com/BlockRunAI/ClawRouter
5262
5562
  `);
5263
5563
  }
5264
5564
  function parseArgs(args) {
5265
- const result = { version: false, help: false, port: void 0 };
5565
+ const result = { version: false, help: false, doctor: false, port: void 0 };
5266
5566
  for (let i = 0; i < args.length; i++) {
5267
5567
  const arg = args[i];
5268
5568
  if (arg === "--version" || arg === "-v") {
5269
5569
  result.version = true;
5270
5570
  } else if (arg === "--help" || arg === "-h") {
5271
5571
  result.help = true;
5572
+ } else if (arg === "doctor" || arg === "--doctor") {
5573
+ result.doctor = true;
5272
5574
  } else if (arg === "--port" && args[i + 1]) {
5273
5575
  result.port = parseInt(args[i + 1], 10);
5274
5576
  i++;
@@ -5286,6 +5588,13 @@ async function main() {
5286
5588
  printHelp();
5287
5589
  process.exit(0);
5288
5590
  }
5591
+ if (args.doctor) {
5592
+ const rawArgs = process.argv.slice(2);
5593
+ const doctorIndex = rawArgs.findIndex((a) => a === "doctor" || a === "--doctor");
5594
+ const userQuestion = rawArgs.slice(doctorIndex + 1).join(" ").trim() || void 0;
5595
+ await runDoctor(userQuestion);
5596
+ process.exit(0);
5597
+ }
5289
5598
  const { key: walletKey, address, source } = await resolveOrGenerateWalletKey();
5290
5599
  if (source === "generated") {
5291
5600
  console.log(`[ClawRouter] Generated new wallet: ${address}`);
@@ -5316,6 +5625,7 @@ async function main() {
5316
5625
  console.error(
5317
5626
  `[ClawRouter] Insufficient funds. Balance: ${info.balanceUSD}, Need: ${info.requiredUSD}`
5318
5627
  );
5628
+ console.error(`[ClawRouter] Run 'npx @blockrun/clawrouter doctor' for funding help`);
5319
5629
  }
5320
5630
  });
5321
5631
  const monitor = new BalanceMonitor(address);
@@ -5352,6 +5662,7 @@ async function main() {
5352
5662
  }
5353
5663
  main().catch((err) => {
5354
5664
  console.error(`[ClawRouter] Fatal error: ${err.message}`);
5665
+ console.error(`[ClawRouter] Run 'npx @blockrun/clawrouter doctor' for AI-powered diagnostics`);
5355
5666
  process.exit(1);
5356
5667
  });
5357
5668
  //# sourceMappingURL=cli.js.map