@blockrun/clawrouter 0.9.4 → 0.9.6
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 +15 -15
- package/dist/cli.js +21 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -335,14 +335,14 @@ Track your savings with `/stats` in any OpenClaw conversation.
|
|
|
335
335
|
|
|
336
336
|
They're built for developers. ClawRouter is built for **agents**.
|
|
337
337
|
|
|
338
|
-
|
|
|
339
|
-
|
|
|
340
|
-
| **Setup**
|
|
341
|
-
| **Auth**
|
|
342
|
-
| **Payment**
|
|
343
|
-
| **Routing**
|
|
344
|
-
| **Rate limits** | Per-key quotas
|
|
345
|
-
| **Cost**
|
|
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 |
|
|
346
346
|
|
|
347
347
|
Agents shouldn't need a human to paste API keys. They should generate a wallet, receive funds, and pay per request — programmatically.
|
|
348
348
|
|
|
@@ -350,13 +350,13 @@ Agents shouldn't need a human to paste API keys. They should generate a wallet,
|
|
|
350
350
|
|
|
351
351
|
Based on [50+ OpenClaw issues](https://github.com/openclaw/openclaw/issues?q=openrouter):
|
|
352
352
|
|
|
353
|
-
| Issue
|
|
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)
|
|
357
|
-
| [#8615](https://github.com/openclaw/openclaw/issues/8615)
|
|
358
|
-
| [#2963](https://github.com/openclaw/openclaw/issues/2963)
|
|
359
|
-
| [#10687](https://github.com/openclaw/openclaw/issues/10687) | "Unknown model" errors
|
|
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
360
|
|
|
361
361
|
**[Full comparison →](docs/vs-openrouter.md)**
|
|
362
362
|
|
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
|
}
|
|
@@ -2018,9 +2019,11 @@ var RequestDeduplicator = class {
|
|
|
2018
2019
|
removeInflight(key) {
|
|
2019
2020
|
const entry = this.inflight.get(key);
|
|
2020
2021
|
if (entry) {
|
|
2021
|
-
const errorBody = Buffer.from(
|
|
2022
|
-
|
|
2023
|
-
|
|
2022
|
+
const errorBody = Buffer.from(
|
|
2023
|
+
JSON.stringify({
|
|
2024
|
+
error: { message: "Original request failed, please retry", type: "dedup_origin_failed" }
|
|
2025
|
+
})
|
|
2026
|
+
);
|
|
2024
2027
|
for (const resolve of entry.resolvers) {
|
|
2025
2028
|
resolve({
|
|
2026
2029
|
status: 503,
|
|
@@ -3106,6 +3109,7 @@ var ROUTING_PROFILES = /* @__PURE__ */ new Set([
|
|
|
3106
3109
|
"premium"
|
|
3107
3110
|
]);
|
|
3108
3111
|
var FREE_MODEL = "nvidia/gpt-oss-120b";
|
|
3112
|
+
var MAX_MESSAGES = 200;
|
|
3109
3113
|
var HEARTBEAT_INTERVAL_MS = 2e3;
|
|
3110
3114
|
var DEFAULT_REQUEST_TIMEOUT_MS = 18e4;
|
|
3111
3115
|
var MAX_FALLBACK_ATTEMPTS = 5;
|
|
@@ -3414,6 +3418,17 @@ function normalizeMessagesForThinking(messages) {
|
|
|
3414
3418
|
});
|
|
3415
3419
|
return hasChanges ? normalized : messages;
|
|
3416
3420
|
}
|
|
3421
|
+
function truncateMessages(messages) {
|
|
3422
|
+
if (!messages || messages.length <= MAX_MESSAGES) return messages;
|
|
3423
|
+
const systemMsgs = messages.filter((m) => m.role === "system");
|
|
3424
|
+
const conversationMsgs = messages.filter((m) => m.role !== "system");
|
|
3425
|
+
const maxConversation = MAX_MESSAGES - systemMsgs.length;
|
|
3426
|
+
const truncatedConversation = conversationMsgs.slice(-maxConversation);
|
|
3427
|
+
console.log(
|
|
3428
|
+
`[ClawRouter] Truncated messages: ${messages.length} \u2192 ${systemMsgs.length + truncatedConversation.length} (kept ${systemMsgs.length} system + ${truncatedConversation.length} recent)`
|
|
3429
|
+
);
|
|
3430
|
+
return [...systemMsgs, ...truncatedConversation];
|
|
3431
|
+
}
|
|
3417
3432
|
var KIMI_BLOCK_RE = /<[||][^<>]*begin[^<>]*[||]>[\s\S]*?<[||][^<>]*end[^<>]*[||]>/gi;
|
|
3418
3433
|
var KIMI_TOKEN_RE = /<[||][^<>]*[||]>/g;
|
|
3419
3434
|
var THINKING_TAG_RE = /<\s*\/?\s*(?:think(?:ing)?|thought|antthinking)\b[^>]*>/gi;
|
|
@@ -3723,6 +3738,9 @@ async function tryModelRequest(upstreamUrl, method, headers, body, modelId, maxT
|
|
|
3723
3738
|
if (Array.isArray(parsed.messages)) {
|
|
3724
3739
|
parsed.messages = normalizeMessageRoles(parsed.messages);
|
|
3725
3740
|
}
|
|
3741
|
+
if (Array.isArray(parsed.messages)) {
|
|
3742
|
+
parsed.messages = truncateMessages(parsed.messages);
|
|
3743
|
+
}
|
|
3726
3744
|
if (Array.isArray(parsed.messages)) {
|
|
3727
3745
|
parsed.messages = sanitizeToolIds(parsed.messages);
|
|
3728
3746
|
}
|