@blockrun/clawrouter 0.12.247 → 0.12.249
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/cli.js +20 -5
- package/dist/index.js +20 -5
- package/docs/image-generation.md +23 -23
- package/package.json +2 -1
- package/skills/clawrouter/SKILL.md +1 -1
package/dist/cli.js
CHANGED
|
@@ -89132,6 +89132,9 @@ function stripThinkingTokens(content) {
|
|
|
89132
89132
|
cleaned = cleaned.replace(THINKING_TAG_RE, "");
|
|
89133
89133
|
return cleaned;
|
|
89134
89134
|
}
|
|
89135
|
+
function forwardToolCallProse() {
|
|
89136
|
+
return process.env.CLAWROUTER_TOOL_CALL_PROSE?.trim().toLowerCase() !== "off";
|
|
89137
|
+
}
|
|
89135
89138
|
function buildModelPricing() {
|
|
89136
89139
|
const map = /* @__PURE__ */ new Map();
|
|
89137
89140
|
for (const m of BLOCKRUN_MODELS) {
|
|
@@ -89545,7 +89548,15 @@ async function startProxy(options) {
|
|
|
89545
89548
|
}
|
|
89546
89549
|
if (full) {
|
|
89547
89550
|
try {
|
|
89548
|
-
const balanceInfo = await
|
|
89551
|
+
const balanceInfo = await Promise.race([
|
|
89552
|
+
balanceMonitor.checkBalance(),
|
|
89553
|
+
new Promise(
|
|
89554
|
+
(_, reject) => setTimeout(
|
|
89555
|
+
() => reject(new Error("balance check timed out")),
|
|
89556
|
+
BALANCE_CHECK_TIMEOUT_MS
|
|
89557
|
+
).unref()
|
|
89558
|
+
)
|
|
89559
|
+
]);
|
|
89549
89560
|
response.balance = balanceInfo.balanceUSD;
|
|
89550
89561
|
response.isLow = balanceInfo.isLow;
|
|
89551
89562
|
response.isEmpty = balanceInfo.isEmpty;
|
|
@@ -92344,13 +92355,16 @@ data: [DONE]
|
|
|
92344
92355
|
const endsWithToolCalls = choice.finish_reason === "tool_calls";
|
|
92345
92356
|
let toolCalls = choice.message?.tool_calls ?? choice.delta?.tool_calls;
|
|
92346
92357
|
const rawContent = choice.message?.content ?? choice.delta?.content ?? "";
|
|
92358
|
+
let proseContent = rawContent;
|
|
92347
92359
|
if (!endsWithToolCalls && (!toolCalls || toolCalls.length === 0) && rawContent) {
|
|
92348
92360
|
const extracted = extractTextualToolCalls(rawContent, { tools: requestTools });
|
|
92349
92361
|
if (extracted.toolCalls.length > 0) {
|
|
92350
92362
|
toolCalls = extracted.toolCalls;
|
|
92363
|
+
proseContent = extracted.cleanedContent;
|
|
92351
92364
|
}
|
|
92352
92365
|
}
|
|
92353
|
-
const
|
|
92366
|
+
const suppressProse = (endsWithToolCalls || toolCalls && toolCalls.length > 0) && !forwardToolCallProse();
|
|
92367
|
+
const content = suppressProse ? "" : stripThinkingTokens(proseContent);
|
|
92354
92368
|
const role = choice.message?.role ?? choice.delta?.role ?? "assistant";
|
|
92355
92369
|
const index2 = choice.index ?? 0;
|
|
92356
92370
|
if (content) {
|
|
@@ -92552,8 +92566,9 @@ data: [DONE]
|
|
|
92552
92566
|
const message = choice.message;
|
|
92553
92567
|
if (!message || typeof message.content !== "string") continue;
|
|
92554
92568
|
if (choice.finish_reason === "tool_calls" || Array.isArray(message.tool_calls) && message.tool_calls.length > 0) {
|
|
92555
|
-
|
|
92556
|
-
|
|
92569
|
+
const next = forwardToolCallProse() ? stripThinkingTokens(message.content) : "";
|
|
92570
|
+
if (message.content !== next) {
|
|
92571
|
+
message.content = next;
|
|
92557
92572
|
changed = true;
|
|
92558
92573
|
}
|
|
92559
92574
|
continue;
|
|
@@ -92561,7 +92576,7 @@ data: [DONE]
|
|
|
92561
92576
|
const extracted = extractTextualToolCalls(message.content, { tools: requestTools });
|
|
92562
92577
|
if (extracted.toolCalls.length > 0) {
|
|
92563
92578
|
message.tool_calls = extracted.toolCalls;
|
|
92564
|
-
message.content = "";
|
|
92579
|
+
message.content = forwardToolCallProse() ? stripThinkingTokens(extracted.cleanedContent) : "";
|
|
92565
92580
|
choice.finish_reason = "tool_calls";
|
|
92566
92581
|
changed = true;
|
|
92567
92582
|
continue;
|
package/dist/index.js
CHANGED
|
@@ -88952,6 +88952,9 @@ function stripThinkingTokens(content) {
|
|
|
88952
88952
|
cleaned = cleaned.replace(THINKING_TAG_RE, "");
|
|
88953
88953
|
return cleaned;
|
|
88954
88954
|
}
|
|
88955
|
+
function forwardToolCallProse() {
|
|
88956
|
+
return process.env.CLAWROUTER_TOOL_CALL_PROSE?.trim().toLowerCase() !== "off";
|
|
88957
|
+
}
|
|
88955
88958
|
function buildModelPricing() {
|
|
88956
88959
|
const map = /* @__PURE__ */ new Map();
|
|
88957
88960
|
for (const m of BLOCKRUN_MODELS) {
|
|
@@ -89365,7 +89368,15 @@ async function startProxy(options) {
|
|
|
89365
89368
|
}
|
|
89366
89369
|
if (full) {
|
|
89367
89370
|
try {
|
|
89368
|
-
const balanceInfo = await
|
|
89371
|
+
const balanceInfo = await Promise.race([
|
|
89372
|
+
balanceMonitor.checkBalance(),
|
|
89373
|
+
new Promise(
|
|
89374
|
+
(_, reject) => setTimeout(
|
|
89375
|
+
() => reject(new Error("balance check timed out")),
|
|
89376
|
+
BALANCE_CHECK_TIMEOUT_MS
|
|
89377
|
+
).unref()
|
|
89378
|
+
)
|
|
89379
|
+
]);
|
|
89369
89380
|
response.balance = balanceInfo.balanceUSD;
|
|
89370
89381
|
response.isLow = balanceInfo.isLow;
|
|
89371
89382
|
response.isEmpty = balanceInfo.isEmpty;
|
|
@@ -92164,13 +92175,16 @@ data: [DONE]
|
|
|
92164
92175
|
const endsWithToolCalls = choice.finish_reason === "tool_calls";
|
|
92165
92176
|
let toolCalls = choice.message?.tool_calls ?? choice.delta?.tool_calls;
|
|
92166
92177
|
const rawContent = choice.message?.content ?? choice.delta?.content ?? "";
|
|
92178
|
+
let proseContent = rawContent;
|
|
92167
92179
|
if (!endsWithToolCalls && (!toolCalls || toolCalls.length === 0) && rawContent) {
|
|
92168
92180
|
const extracted = extractTextualToolCalls(rawContent, { tools: requestTools });
|
|
92169
92181
|
if (extracted.toolCalls.length > 0) {
|
|
92170
92182
|
toolCalls = extracted.toolCalls;
|
|
92183
|
+
proseContent = extracted.cleanedContent;
|
|
92171
92184
|
}
|
|
92172
92185
|
}
|
|
92173
|
-
const
|
|
92186
|
+
const suppressProse = (endsWithToolCalls || toolCalls && toolCalls.length > 0) && !forwardToolCallProse();
|
|
92187
|
+
const content = suppressProse ? "" : stripThinkingTokens(proseContent);
|
|
92174
92188
|
const role = choice.message?.role ?? choice.delta?.role ?? "assistant";
|
|
92175
92189
|
const index2 = choice.index ?? 0;
|
|
92176
92190
|
if (content) {
|
|
@@ -92372,8 +92386,9 @@ data: [DONE]
|
|
|
92372
92386
|
const message = choice.message;
|
|
92373
92387
|
if (!message || typeof message.content !== "string") continue;
|
|
92374
92388
|
if (choice.finish_reason === "tool_calls" || Array.isArray(message.tool_calls) && message.tool_calls.length > 0) {
|
|
92375
|
-
|
|
92376
|
-
|
|
92389
|
+
const next = forwardToolCallProse() ? stripThinkingTokens(message.content) : "";
|
|
92390
|
+
if (message.content !== next) {
|
|
92391
|
+
message.content = next;
|
|
92377
92392
|
changed = true;
|
|
92378
92393
|
}
|
|
92379
92394
|
continue;
|
|
@@ -92381,7 +92396,7 @@ data: [DONE]
|
|
|
92381
92396
|
const extracted = extractTextualToolCalls(message.content, { tools: requestTools });
|
|
92382
92397
|
if (extracted.toolCalls.length > 0) {
|
|
92383
92398
|
message.tool_calls = extracted.toolCalls;
|
|
92384
|
-
message.content = "";
|
|
92399
|
+
message.content = forwardToolCallProse() ? stripThinkingTokens(extracted.cleanedContent) : "";
|
|
92385
92400
|
choice.finish_reason = "tool_calls";
|
|
92386
92401
|
changed = true;
|
|
92387
92402
|
continue;
|
package/docs/image-generation.md
CHANGED
|
@@ -51,17 +51,17 @@ The returned URL is a publicly hosted image, ready to use in Telegram, Discord,
|
|
|
51
51
|
|
|
52
52
|
## Models & Pricing
|
|
53
53
|
|
|
54
|
-
| Model ID | Shorthand | Price
|
|
55
|
-
| ---------------------------- | ------------------ |
|
|
56
|
-
| `google/nano-banana` | `nano-banana` | $0.05/image
|
|
57
|
-
| `google/nano-banana-2` | `banana-2` | $0.09/image
|
|
58
|
-
| `google/nano-banana-pro` | `banana-pro` | $0.10–$0.15/image
|
|
59
|
-
| `openai/gpt-image-1` | `gpt-image` | $0.02–$0.04/image
|
|
60
|
-
| `openai/gpt-image-2` | `gpt-image-2` | $0.06–$0.12/image
|
|
61
|
-
| `bytedance/seedream-5-pro` | `seedream` | $0.045–$0.09/image
|
|
62
|
-
| `xai/grok-imagine-image` | `grok-imagine` | $0.02/image
|
|
63
|
-
| `xai/grok-imagine-image-pro` | `grok-imagine-pro` | $0.07/image
|
|
64
|
-
| `zai/cogview-4` | `cogview` | $0.015–$0.02/image
|
|
54
|
+
| Model ID | Shorthand | Price | Sizes | Provider |
|
|
55
|
+
| ---------------------------- | ------------------ | ------------------ | ------------------------------------------------------------------------------------- | -------------------- |
|
|
56
|
+
| `google/nano-banana` | `nano-banana` | $0.05/image | 1024×1024 | Google Gemini Flash |
|
|
57
|
+
| `google/nano-banana-2` | `banana-2` | $0.09/image | 1024×1024 | Google Nano Banana 2 |
|
|
58
|
+
| `google/nano-banana-pro` | `banana-pro` | $0.10–$0.15/image | 1024×1024, 2048×2048, 4096×4096 | Google Gemini Pro |
|
|
59
|
+
| `openai/gpt-image-1` | `gpt-image` | $0.02–$0.04/image | 1024×1024, 1536×1024, 1024×1536 | OpenAI GPT Image 1 |
|
|
60
|
+
| `openai/gpt-image-2` | `gpt-image-2` | $0.06–$0.12/image | 1024×1024, 1536×1024, 1024×1536 | OpenAI GPT Image 2 |
|
|
61
|
+
| `bytedance/seedream-5-pro` | `seedream` | $0.045–$0.09/image | 1024×1024, 1280×720, 2048×1024, 2048×2048, 2304×1728, 1728×2304, 2848×1600, 1600×2848 | ByteDance Seedream 5 |
|
|
62
|
+
| `xai/grok-imagine-image` | `grok-imagine` | $0.02/image | 1024×1024 | xAI Grok Imagine |
|
|
63
|
+
| `xai/grok-imagine-image-pro` | `grok-imagine-pro` | $0.07/image | 1024×1024 | xAI Grok Imagine Pro |
|
|
64
|
+
| `zai/cogview-4` | `cogview` | $0.015–$0.02/image | 512×512, 768×768, 1024×1024, 768×1344, 1344×768, 1440×1440 | Zhipu CogView-4 |
|
|
65
65
|
|
|
66
66
|
Default model: `google/nano-banana`.
|
|
67
67
|
|
|
@@ -369,18 +369,18 @@ When using ClawRouter with OpenClaw, generate and edit images directly from any
|
|
|
369
369
|
|
|
370
370
|
### Model shorthands
|
|
371
371
|
|
|
372
|
-
| Shorthand
|
|
373
|
-
|
|
|
374
|
-
| `nano-banana`, `banana`
|
|
375
|
-
| `banana-2`, `nano-banana-2`
|
|
376
|
-
| `banana-pro`, `nano-banana-pro`
|
|
377
|
-
| `gpt-image`, `gpt-image-1`
|
|
378
|
-
| `gpt-image-2`
|
|
379
|
-
| `seedream`
|
|
380
|
-
| `grok-imagine`
|
|
381
|
-
| `grok-imagine-pro`
|
|
382
|
-
| `cogview`
|
|
383
|
-
| `dall-e-3`, `dalle3`, `dalle` (legacy) | `openai/gpt-image-2`
|
|
372
|
+
| Shorthand | Full ID |
|
|
373
|
+
| -------------------------------------- | ---------------------------- |
|
|
374
|
+
| `nano-banana`, `banana` | `google/nano-banana` |
|
|
375
|
+
| `banana-2`, `nano-banana-2` | `google/nano-banana-2` |
|
|
376
|
+
| `banana-pro`, `nano-banana-pro` | `google/nano-banana-pro` |
|
|
377
|
+
| `gpt-image`, `gpt-image-1` | `openai/gpt-image-1` |
|
|
378
|
+
| `gpt-image-2` | `openai/gpt-image-2` |
|
|
379
|
+
| `seedream` | `bytedance/seedream-5-pro` |
|
|
380
|
+
| `grok-imagine` | `xai/grok-imagine-image` |
|
|
381
|
+
| `grok-imagine-pro` | `xai/grok-imagine-image-pro` |
|
|
382
|
+
| `cogview` | `zai/cogview-4` |
|
|
383
|
+
| `dall-e-3`, `dalle3`, `dalle` (legacy) | `openai/gpt-image-2` |
|
|
384
384
|
|
|
385
385
|
---
|
|
386
386
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/clawrouter",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.249",
|
|
4
4
|
"description": "Smart LLM router — save 88% on inference costs. 71 models (5 free), one wallet, x402 micropayments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"dev": "tsup --watch",
|
|
45
45
|
"test": "vitest run",
|
|
46
46
|
"test:watch": "vitest",
|
|
47
|
+
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
47
48
|
"typecheck": "tsc --noEmit",
|
|
48
49
|
"lint": "eslint src/",
|
|
49
50
|
"format": "prettier --write .",
|
|
@@ -164,7 +164,7 @@ Realtime prices and historical OHLC across every asset class. The agent should c
|
|
|
164
164
|
|
|
165
165
|
| Tool | Purpose | Price |
|
|
166
166
|
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
|
|
167
|
-
| `blockrun_image_generation` | 9 image models — GPT Image 1/2, Nano Banana / 2 / Pro, Seedream 5 Pro, Grok Imagine / Pro, CogView-4
|
|
167
|
+
| `blockrun_image_generation` | 9 image models — GPT Image 1/2, Nano Banana / 2 / Pro, Seedream 5 Pro, Grok Imagine / Pro, CogView-4 | $0.015–$0.15 / image |
|
|
168
168
|
| `blockrun_image_edit` | Edit / inpaint existing image (openai/gpt-image-1) | $0.02–$0.04 / image |
|
|
169
169
|
| `blockrun_video_generation` | Grok Imagine + ByteDance Seedance (1.5-pro / 2.0-fast / 2.0) at 720p with synced audio (t2v default), 5–10s, + OpenAI Sora 2 via Azure (`azure/sora-2`, 4/8/12s, t2v + i2v, rejects human faces in reference images). Seedance is token-priced upstream (~20,256 tokens/sec at the 720p+audio default — 2× the prior 480p rate); `image_url` (image-to-video) costs the same as t2v since 2026-06-01. Seedance 2.0 variants accept optional `real_face_asset_id` (`ta_…`) for BytePlus RealFace character-consistency — mutually exclusive with `image_url`. | $0.05/s (Grok); $0.10/s (Sora 2); Seedance ~$0.46–$1.49 per 5s clip |
|
|
170
170
|
|