@blockrun/clawrouter 0.9.3 โ 0.9.5
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 +34 -23
- package/dist/cli.js +26 -49
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +10 -9
- package/dist/index.js +26 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ One wallet, 30+ models, zero API keys.
|
|
|
11
11
|
[](https://nodejs.org)
|
|
12
12
|
[](https://x.com/USDC/status/2021625822294216977)
|
|
13
13
|
|
|
14
|
-
[Docs](https://blockrun.ai/docs) · [Models](https://blockrun.ai/models) · [
|
|
14
|
+
[Docs](https://blockrun.ai/docs) · [Models](https://blockrun.ai/models) · [vs OpenRouter](docs/vs-openrouter.md) · [Configuration](docs/configuration.md) · [Features](docs/features.md) · [Troubleshooting](docs/troubleshooting.md) · [Telegram](https://t.me/blockrunAI) · [X](https://x.com/BlockRunAI)
|
|
15
15
|
|
|
16
16
|
**Winner โ Agentic Commerce Track** at the [USDC AI Agent Hackathon](https://x.com/USDC/status/2021625822294216977)<br>
|
|
17
17
|
_The world's first hackathon run entirely by AI agents, powered by USDC_
|
|
@@ -58,22 +58,6 @@ openclaw gateway restart
|
|
|
58
58
|
|
|
59
59
|
Done! Smart routing (`blockrun/auto`) is now your default model.
|
|
60
60
|
|
|
61
|
-
### Windows Installation
|
|
62
|
-
|
|
63
|
-
โ ๏ธ **Current Status:** Windows installation is temporarily unavailable due to an OpenClaw CLI bug. The issue is with the OpenClaw framework, not ClawRouter itself.
|
|
64
|
-
|
|
65
|
-
**๐ Full Windows Guide:** [docs/windows-installation.md](docs/windows-installation.md)
|
|
66
|
-
|
|
67
|
-
**Quick Summary:**
|
|
68
|
-
|
|
69
|
-
- โ
ClawRouter code is Windows-compatible
|
|
70
|
-
- โ OpenClaw CLI has a `spawn EINVAL` bug on Windows
|
|
71
|
-
- โ
Works perfectly on **Linux** and **macOS**
|
|
72
|
-
- ๐ง Manual installation workaround available for advanced users
|
|
73
|
-
- ๐งช Full Windows test infrastructure ready ([.github/workflows/test-windows.yml](.github/workflows/test-windows.yml))
|
|
74
|
-
|
|
75
|
-
**For advanced users:** See the [complete manual installation guide](docs/windows-installation.md) with step-by-step PowerShell instructions.
|
|
76
|
-
|
|
77
61
|
### Routing Profiles
|
|
78
62
|
|
|
79
63
|
Choose your routing strategy with `/model <profile>`:
|
|
@@ -351,15 +335,31 @@ Track your savings with `/stats` in any OpenClaw conversation.
|
|
|
351
335
|
|
|
352
336
|
They're built for developers. ClawRouter is built for **agents**.
|
|
353
337
|
|
|
354
|
-
|
|
|
355
|
-
|
|
|
356
|
-
| **Setup**
|
|
357
|
-
| **Auth**
|
|
358
|
-
| **Payment**
|
|
359
|
-
| **Routing**
|
|
338
|
+
| | OpenRouter / LiteLLM | ClawRouter |
|
|
339
|
+
| --------------- | --------------------------- | -------------------------------- |
|
|
340
|
+
| **Setup** | Human creates account | Agent generates wallet |
|
|
341
|
+
| **Auth** | API key (shared secret) | Wallet signature (cryptographic) |
|
|
342
|
+
| **Payment** | Prepaid balance (custodial) | Per-request (non-custodial) |
|
|
343
|
+
| **Routing** | Proprietary / closed | Open source, client-side |
|
|
344
|
+
| **Rate limits** | Per-key quotas | None (your wallet, your limits) |
|
|
345
|
+
| **Cost** | $25/M (Opus equivalent) | $2.05/M blended average |
|
|
360
346
|
|
|
361
347
|
Agents shouldn't need a human to paste API keys. They should generate a wallet, receive funds, and pay per request โ programmatically.
|
|
362
348
|
|
|
349
|
+
### Real Problems with OpenRouter
|
|
350
|
+
|
|
351
|
+
Based on [50+ OpenClaw issues](https://github.com/openclaw/openclaw/issues?q=openrouter):
|
|
352
|
+
|
|
353
|
+
| Issue | Problem | ClawRouter |
|
|
354
|
+
| ----------------------------------------------------------- | ----------------------------------- | -------------------------- |
|
|
355
|
+
| [#11202](https://github.com/openclaw/openclaw/issues/11202) | API keys leaked in every LLM prompt | No API keys to leak |
|
|
356
|
+
| [#2373](https://github.com/openclaw/openclaw/issues/2373) | `openrouter/auto` path broken | `blockrun/auto` just works |
|
|
357
|
+
| [#8615](https://github.com/openclaw/openclaw/issues/8615) | Single API key rate limit hell | Non-custodial, no limits |
|
|
358
|
+
| [#2963](https://github.com/openclaw/openclaw/issues/2963) | Tool calling fails silently | Full tool support |
|
|
359
|
+
| [#10687](https://github.com/openclaw/openclaw/issues/10687) | "Unknown model" errors | 30+ models, auto-update |
|
|
360
|
+
|
|
361
|
+
**[Full comparison โ](docs/vs-openrouter.md)**
|
|
362
|
+
|
|
363
363
|
---
|
|
364
364
|
|
|
365
365
|
## Troubleshooting
|
|
@@ -399,6 +399,17 @@ BLOCKRUN_WALLET_KEY=0x... npx tsx test-e2e.ts
|
|
|
399
399
|
|
|
400
400
|
---
|
|
401
401
|
|
|
402
|
+
## Uninstall
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
openclaw plugins uninstall clawrouter
|
|
406
|
+
openclaw gateway restart
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Your wallet key remains at `~/.openclaw/blockrun/wallet.key` โ back it up before deleting if you have funds.
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
402
413
|
## Roadmap
|
|
403
414
|
|
|
404
415
|
- [x] Smart routing โ 15-dimension weighted scoring, 4-tier model selection
|
package/dist/cli.js
CHANGED
|
@@ -1388,6 +1388,7 @@ function resolveModelAlias(model) {
|
|
|
1388
1388
|
const withoutPrefix = normalized.slice("blockrun/".length);
|
|
1389
1389
|
const resolvedWithoutPrefix = MODEL_ALIASES[withoutPrefix];
|
|
1390
1390
|
if (resolvedWithoutPrefix) return resolvedWithoutPrefix;
|
|
1391
|
+
return withoutPrefix;
|
|
1391
1392
|
}
|
|
1392
1393
|
return model;
|
|
1393
1394
|
}
|
|
@@ -1989,26 +1990,14 @@ var RequestDeduplicator = class {
|
|
|
1989
1990
|
getInflight(key) {
|
|
1990
1991
|
const entry = this.inflight.get(key);
|
|
1991
1992
|
if (!entry) return void 0;
|
|
1992
|
-
|
|
1993
|
-
entry.
|
|
1994
|
-
new Promise((r) => {
|
|
1995
|
-
const orig = entry.resolve;
|
|
1996
|
-
entry.resolve = (result) => {
|
|
1997
|
-
orig(result);
|
|
1998
|
-
resolve(result);
|
|
1999
|
-
r(result);
|
|
2000
|
-
};
|
|
2001
|
-
})
|
|
2002
|
-
);
|
|
1993
|
+
return new Promise((resolve) => {
|
|
1994
|
+
entry.resolvers.push(resolve);
|
|
2003
1995
|
});
|
|
2004
|
-
return promise;
|
|
2005
1996
|
}
|
|
2006
1997
|
/** Mark a request as in-flight. */
|
|
2007
1998
|
markInflight(key) {
|
|
2008
1999
|
this.inflight.set(key, {
|
|
2009
|
-
|
|
2010
|
-
},
|
|
2011
|
-
waiters: []
|
|
2000
|
+
resolvers: []
|
|
2012
2001
|
});
|
|
2013
2002
|
}
|
|
2014
2003
|
/** Complete an in-flight request โ cache result and notify waiters. */
|
|
@@ -2018,14 +2007,33 @@ var RequestDeduplicator = class {
|
|
|
2018
2007
|
}
|
|
2019
2008
|
const entry = this.inflight.get(key);
|
|
2020
2009
|
if (entry) {
|
|
2021
|
-
entry.
|
|
2010
|
+
for (const resolve of entry.resolvers) {
|
|
2011
|
+
resolve(result);
|
|
2012
|
+
}
|
|
2022
2013
|
this.inflight.delete(key);
|
|
2023
2014
|
}
|
|
2024
2015
|
this.prune();
|
|
2025
2016
|
}
|
|
2026
|
-
/** Remove an in-flight entry on error (don't cache failures).
|
|
2017
|
+
/** Remove an in-flight entry on error (don't cache failures).
|
|
2018
|
+
* Also rejects any waiters so they can retry independently. */
|
|
2027
2019
|
removeInflight(key) {
|
|
2028
|
-
this.inflight.
|
|
2020
|
+
const entry = this.inflight.get(key);
|
|
2021
|
+
if (entry) {
|
|
2022
|
+
const errorBody = Buffer.from(
|
|
2023
|
+
JSON.stringify({
|
|
2024
|
+
error: { message: "Original request failed, please retry", type: "dedup_origin_failed" }
|
|
2025
|
+
})
|
|
2026
|
+
);
|
|
2027
|
+
for (const resolve of entry.resolvers) {
|
|
2028
|
+
resolve({
|
|
2029
|
+
status: 503,
|
|
2030
|
+
headers: { "content-type": "application/json" },
|
|
2031
|
+
body: errorBody,
|
|
2032
|
+
completedAt: Date.now()
|
|
2033
|
+
});
|
|
2034
|
+
}
|
|
2035
|
+
this.inflight.delete(key);
|
|
2036
|
+
}
|
|
2029
2037
|
}
|
|
2030
2038
|
/** Prune expired completed entries. */
|
|
2031
2039
|
prune() {
|
|
@@ -3886,7 +3894,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3886
3894
|
}
|
|
3887
3895
|
const autoCompress = options.autoCompressRequests ?? true;
|
|
3888
3896
|
const compressionThreshold = options.compressionThresholdKB ?? 180;
|
|
3889
|
-
const sizeLimit = options.maxRequestSizeKB ?? 200;
|
|
3890
3897
|
const requestSizeKB = Math.ceil(body.length / 1024);
|
|
3891
3898
|
if (autoCompress && requestSizeKB > compressionThreshold) {
|
|
3892
3899
|
try {
|
|
@@ -3928,21 +3935,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3928
3935
|
);
|
|
3929
3936
|
parsed.messages = compressionResult.messages;
|
|
3930
3937
|
body = Buffer.from(JSON.stringify(parsed));
|
|
3931
|
-
if (compressedSizeKB > sizeLimit) {
|
|
3932
|
-
const errorMsg = {
|
|
3933
|
-
error: {
|
|
3934
|
-
message: `Request size ${compressedSizeKB}KB still exceeds limit after compression (original: ${requestSizeKB}KB). Please reduce context size.`,
|
|
3935
|
-
type: "request_too_large",
|
|
3936
|
-
original_size_kb: requestSizeKB,
|
|
3937
|
-
compressed_size_kb: compressedSizeKB,
|
|
3938
|
-
limit_kb: sizeLimit,
|
|
3939
|
-
help: "Try: 1) Remove old messages from history, 2) Summarize large tool results, 3) Use direct API for very large contexts"
|
|
3940
|
-
}
|
|
3941
|
-
};
|
|
3942
|
-
res.writeHead(413, { "Content-Type": "application/json" });
|
|
3943
|
-
res.end(JSON.stringify(errorMsg));
|
|
3944
|
-
return;
|
|
3945
|
-
}
|
|
3946
3938
|
}
|
|
3947
3939
|
} catch (err) {
|
|
3948
3940
|
console.warn(
|
|
@@ -3950,21 +3942,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3950
3942
|
);
|
|
3951
3943
|
}
|
|
3952
3944
|
}
|
|
3953
|
-
const finalSizeKB = Math.ceil(body.length / 1024);
|
|
3954
|
-
if (finalSizeKB > sizeLimit) {
|
|
3955
|
-
const errorMsg = {
|
|
3956
|
-
error: {
|
|
3957
|
-
message: `Request size ${finalSizeKB}KB exceeds limit ${sizeLimit}KB. Please reduce context size.`,
|
|
3958
|
-
type: "request_too_large",
|
|
3959
|
-
size_kb: finalSizeKB,
|
|
3960
|
-
limit_kb: sizeLimit,
|
|
3961
|
-
help: "Try: 1) Remove old messages from history, 2) Summarize large tool results, 3) Enable compression (autoCompressRequests: true)"
|
|
3962
|
-
}
|
|
3963
|
-
};
|
|
3964
|
-
res.writeHead(413, { "Content-Type": "application/json" });
|
|
3965
|
-
res.end(JSON.stringify(errorMsg));
|
|
3966
|
-
return;
|
|
3967
|
-
}
|
|
3968
3945
|
const dedupKey = RequestDeduplicator.hash(body);
|
|
3969
3946
|
const cached = deduplicator.getCached(dedupKey);
|
|
3970
3947
|
if (cached) {
|