@blockrun/clawrouter 0.12.61 → 0.12.63
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/docs/anthropic-cost-savings.md +349 -0
- package/docs/architecture.md +559 -0
- package/docs/assets/blockrun-248-day-cost-overrun-problem.png +0 -0
- package/docs/assets/blockrun-clawrouter-7-layer-token-compression-openclaw.png +0 -0
- package/docs/assets/blockrun-clawrouter-observation-compression-97-percent-token-savings.png +0 -0
- package/docs/assets/blockrun-clawrouter-openclaw-agentic-proxy-architecture.png +0 -0
- package/docs/assets/blockrun-clawrouter-openclaw-automatic-tier-routing-model-selection.png +0 -0
- package/docs/assets/blockrun-clawrouter-openclaw-error-classification-retry-storm-prevention.png +0 -0
- package/docs/assets/blockrun-clawrouter-openclaw-session-memory-journaling-vs-context-compounding.png +0 -0
- package/docs/assets/blockrun-clawrouter-vs-openclaw-standalone-comparison-production-safety.png +0 -0
- package/docs/assets/blockrun-clawrouter-x402-usdc-micropayment-wallet-budget-control.png +0 -0
- package/docs/assets/blockrun-openclaw-inference-layer-blind-spots.png +0 -0
- package/docs/blog-benchmark-2026-03.md +184 -0
- package/docs/blog-openclaw-cost-overruns.md +197 -0
- package/docs/clawrouter-savings.png +0 -0
- package/docs/configuration.md +512 -0
- package/docs/features.md +257 -0
- package/docs/image-generation.md +380 -0
- package/docs/plans/2026-02-03-smart-routing-design.md +267 -0
- package/docs/plans/2026-02-13-e2e-docker-deployment.md +1260 -0
- package/docs/plans/2026-02-28-worker-network.md +947 -0
- package/docs/plans/2026-03-18-error-classification.md +574 -0
- package/docs/plans/2026-03-19-exclude-models.md +538 -0
- package/docs/routing-profiles.md +81 -0
- package/docs/subscription-failover.md +320 -0
- package/docs/technical-routing-2026-03.md +322 -0
- package/docs/troubleshooting.md +159 -0
- package/docs/vision.md +49 -0
- package/docs/vs-openrouter.md +157 -0
- package/docs/worker-network.md +1241 -0
- package/package.json +3 -2
- package/scripts/reinstall.sh +8 -4
- package/scripts/update.sh +8 -4
package/docs/features.md
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# Advanced Features
|
|
2
|
+
|
|
3
|
+
ClawRouter v0.5+ includes intelligent routing features that work automatically.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Response Cache](#response-cache)
|
|
8
|
+
- [Agentic Auto-Detection](#agentic-auto-detection)
|
|
9
|
+
- [Tool Detection](#tool-detection)
|
|
10
|
+
- [Context-Length-Aware Routing](#context-length-aware-routing)
|
|
11
|
+
- [Model Aliases](#model-aliases)
|
|
12
|
+
- [Free Tier Fallback](#free-tier-fallback)
|
|
13
|
+
- [Session Persistence](#session-persistence)
|
|
14
|
+
- [Cost Tracking with /stats](#cost-tracking-with-stats)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Response Cache
|
|
19
|
+
|
|
20
|
+
ClawRouter includes LLM response caching inspired by LiteLLM's caching system. Identical requests return cached responses, saving both cost and latency.
|
|
21
|
+
|
|
22
|
+
**How it works:**
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
Request: "What is 2+2?"
|
|
26
|
+
First call: → API ($0.001) → Cache response
|
|
27
|
+
Second call: → Cache HIT → Return instantly ($0)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Features:**
|
|
31
|
+
|
|
32
|
+
| Feature | Default | Description |
|
|
33
|
+
| ------------ | ----------- | -------------------------- |
|
|
34
|
+
| TTL | 10 minutes | Responses expire after TTL |
|
|
35
|
+
| Max size | 200 entries | LRU eviction when full |
|
|
36
|
+
| Item limit | 1MB | Large responses skipped |
|
|
37
|
+
| Auto-enabled | Yes | No config needed |
|
|
38
|
+
|
|
39
|
+
**Cache key generation:**
|
|
40
|
+
|
|
41
|
+
The cache key is a SHA-256 hash of the request body (model + messages + params), with normalization:
|
|
42
|
+
|
|
43
|
+
- Message timestamps stripped (OpenClaw injects `[Mon 2024-01-15 10:30 UTC]`)
|
|
44
|
+
- Keys sorted for consistent hashing
|
|
45
|
+
- Stream mode, user, and request_id fields excluded
|
|
46
|
+
|
|
47
|
+
**Bypass cache:**
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Via header
|
|
51
|
+
fetch("/v1/chat/completions", {
|
|
52
|
+
headers: { "Cache-Control": "no-cache" }
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Via body
|
|
56
|
+
{
|
|
57
|
+
"model": "blockrun/auto",
|
|
58
|
+
"cache": false, // or "no_cache": true
|
|
59
|
+
"messages": [...]
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Check cache stats:**
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
curl http://localhost:8402/cache
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Response:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"size": 42,
|
|
74
|
+
"maxSize": 200,
|
|
75
|
+
"hits": 156,
|
|
76
|
+
"misses": 89,
|
|
77
|
+
"evictions": 3,
|
|
78
|
+
"hitRate": "63.7%"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Configuration:**
|
|
83
|
+
|
|
84
|
+
Response caching is enabled by default with sensible defaults. For advanced tuning, the cache can be configured programmatically:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { ResponseCache } from "@blockrun/clawrouter";
|
|
88
|
+
|
|
89
|
+
const cache = new ResponseCache({
|
|
90
|
+
maxSize: 500, // Max cached responses
|
|
91
|
+
defaultTTL: 300, // 5 minutes
|
|
92
|
+
maxItemSize: 2_097_152, // 2MB max per item
|
|
93
|
+
enabled: true,
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Agentic Auto-Detection
|
|
100
|
+
|
|
101
|
+
ClawRouter automatically detects multi-step agentic tasks and routes to models optimized for autonomous execution:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
"what is 2+2" → gemini-flash (standard)
|
|
105
|
+
"build the project then run tests" → kimi-k2.5 (auto-agentic)
|
|
106
|
+
"fix the bug and make sure it works" → kimi-k2.5 (auto-agentic)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**How it works:**
|
|
110
|
+
|
|
111
|
+
- Detects agentic keywords: file ops ("read", "edit"), execution ("run", "test", "deploy"), iteration ("fix", "debug", "verify")
|
|
112
|
+
- Threshold: 2+ signals triggers auto-switch to agentic tiers
|
|
113
|
+
- No config needed — works automatically
|
|
114
|
+
|
|
115
|
+
**Agentic tier models** (optimized for multi-step autonomy):
|
|
116
|
+
|
|
117
|
+
| Tier | Agentic Model | Why |
|
|
118
|
+
| --------- | ----------------- | ------------------------------ |
|
|
119
|
+
| SIMPLE | claude-haiku-4.5 | Fast + reliable tool use |
|
|
120
|
+
| MEDIUM | kimi-k2.5 | 200+ tool chains, 76% cheaper |
|
|
121
|
+
| COMPLEX | claude-sonnet-4.6 | Best balance for complex tasks |
|
|
122
|
+
| REASONING | kimi-k2.5 | Extended reasoning + execution |
|
|
123
|
+
|
|
124
|
+
### Force Agentic Mode
|
|
125
|
+
|
|
126
|
+
You can also force agentic mode via config:
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
# openclaw.yaml
|
|
130
|
+
plugins:
|
|
131
|
+
- id: "@blockrun/clawrouter"
|
|
132
|
+
config:
|
|
133
|
+
routing:
|
|
134
|
+
overrides:
|
|
135
|
+
agenticMode: true # Always use agentic tiers
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Tool Detection
|
|
141
|
+
|
|
142
|
+
When your request includes a `tools` array (function calling), ClawRouter automatically switches to agentic tiers:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Request with tools → auto-agentic mode
|
|
146
|
+
{
|
|
147
|
+
model: "blockrun/auto",
|
|
148
|
+
messages: [{ role: "user", content: "Check the weather" }],
|
|
149
|
+
tools: [{ type: "function", function: { name: "get_weather", ... } }]
|
|
150
|
+
}
|
|
151
|
+
// → Routes to claude-haiku-4.5 (excellent tool use)
|
|
152
|
+
// → Instead of gemini-flash (may produce malformed tool calls)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**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.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Context-Length-Aware Routing
|
|
160
|
+
|
|
161
|
+
ClawRouter automatically filters out models that can't handle your context size:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
150K token request:
|
|
165
|
+
Full chain: [grok-4-fast (131K), deepseek (128K), kimi (262K), gemini (1M)]
|
|
166
|
+
Filtered: [kimi (262K), gemini (1M)]
|
|
167
|
+
→ Skips models that would fail with "context too long" errors
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
This prevents wasted API calls and faster fallback to capable models.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Model Aliases
|
|
175
|
+
|
|
176
|
+
Use short aliases instead of full model paths:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
/model free # gpt-oss-120b (FREE!)
|
|
180
|
+
/model br-sonnet # anthropic/claude-sonnet-4.6
|
|
181
|
+
/model br-opus # anthropic/claude-opus-4
|
|
182
|
+
/model br-haiku # anthropic/claude-haiku-4.5
|
|
183
|
+
/model gpt # openai/gpt-4o
|
|
184
|
+
/model gpt5 # openai/gpt-5.2
|
|
185
|
+
/model deepseek # deepseek/deepseek-chat
|
|
186
|
+
/model reasoner # deepseek/deepseek-reasoner
|
|
187
|
+
/model kimi # moonshot/kimi-k2.5
|
|
188
|
+
/model gemini # google/gemini-2.5-pro
|
|
189
|
+
/model flash # google/gemini-2.5-flash
|
|
190
|
+
/model grok # xai/grok-3
|
|
191
|
+
/model grok-fast # xai/grok-4-fast-reasoning
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
All aliases work with `/model blockrun/xxx` or just `/model xxx`.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Free Tier Fallback
|
|
199
|
+
|
|
200
|
+
When your wallet balance hits $0, ClawRouter automatically falls back to the free model (`gpt-oss-120b`):
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
Wallet: $0.00
|
|
204
|
+
Request: "Help me write a function"
|
|
205
|
+
→ Routes to gpt-oss-120b (FREE)
|
|
206
|
+
→ No "insufficient funds" error
|
|
207
|
+
→ Keep building while you top up
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
You'll never get blocked by an empty wallet — the free tier keeps you running.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Session Persistence
|
|
215
|
+
|
|
216
|
+
For multi-turn conversations, ClawRouter pins the model to prevent mid-task switching:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
Turn 1: "Build a React component" → claude-sonnet-4.6
|
|
220
|
+
Turn 2: "Add dark mode support" → claude-sonnet-4.6 (pinned)
|
|
221
|
+
Turn 3: "Now add tests" → claude-sonnet-4.6 (pinned)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Sessions are identified by conversation ID and persist for 1 hour of inactivity.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Cost Tracking with /stats
|
|
229
|
+
|
|
230
|
+
Track your savings in real-time:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
# In any OpenClaw conversation
|
|
234
|
+
/stats
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Output:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
+============================================================+
|
|
241
|
+
| ClawRouter Usage Statistics |
|
|
242
|
+
+============================================================+
|
|
243
|
+
| Period: last 7 days |
|
|
244
|
+
| Total Requests: 442 |
|
|
245
|
+
| Total Cost: $1.73 |
|
|
246
|
+
| Baseline Cost (Opus): $20.13 |
|
|
247
|
+
| Total Saved: $18.40 (91.4%) |
|
|
248
|
+
+------------------------------------------------------------+
|
|
249
|
+
| Routing by Tier: |
|
|
250
|
+
| SIMPLE =========== 55.0% (243) |
|
|
251
|
+
| MEDIUM ====== 30.8% (136) |
|
|
252
|
+
| COMPLEX = 7.2% (32) |
|
|
253
|
+
| REASONING = 7.0% (31) |
|
|
254
|
+
+============================================================+
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Stats are stored locally at `~/.openclaw/blockrun/logs/` and aggregated on demand.
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
# Image Generation & Editing
|
|
2
|
+
|
|
3
|
+
Generate and edit images via BlockRun's image API with x402 micropayments — no API keys, pay per image.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Quick Start](#quick-start)
|
|
8
|
+
- [Models & Pricing](#models--pricing)
|
|
9
|
+
- [API Reference](#api-reference)
|
|
10
|
+
- [POST /v1/images/generations](#post-v1imagesgenerations)
|
|
11
|
+
- [POST /v1/images/image2image](#post-v1imagesimage2image)
|
|
12
|
+
- [Code Examples](#code-examples)
|
|
13
|
+
- [Image Generation](#image-generation-examples)
|
|
14
|
+
- [Image Editing (img2img)](#image-editing-examples)
|
|
15
|
+
- [In-Chat Commands](#in-chat-commands)
|
|
16
|
+
- [Notes](#notes)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
ClawRouter runs a local proxy on port `8402` that handles x402 payments automatically. Point any OpenAI-compatible client at it:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
curl -X POST http://localhost:8402/v1/images/generations \
|
|
26
|
+
-H "Content-Type: application/json" \
|
|
27
|
+
-d '{
|
|
28
|
+
"model": "google/nano-banana",
|
|
29
|
+
"prompt": "a golden retriever surfing on a wave",
|
|
30
|
+
"size": "1024x1024",
|
|
31
|
+
"n": 1
|
|
32
|
+
}'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Response:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"created": 1741460000,
|
|
40
|
+
"data": [
|
|
41
|
+
{
|
|
42
|
+
"url": "https://files.catbox.moe/abc123.png"
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The returned URL is a publicly hosted image, ready to use in Telegram, Discord, or any client.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Models & Pricing
|
|
53
|
+
|
|
54
|
+
| Model ID | Shorthand | Price | Max Size | Provider |
|
|
55
|
+
| -------------------------- | --------------- | ----------- | ---------- | ----------------- |
|
|
56
|
+
| `google/nano-banana` | `nano-banana` | $0.05/image | 1024×1024 | Google Gemini Flash |
|
|
57
|
+
| `google/nano-banana-pro` | `banana-pro` | $0.10/image | 4096×4096 | Google Gemini Pro |
|
|
58
|
+
| `openai/dall-e-3` | `dall-e-3` | $0.04/image | 1792×1024 | OpenAI DALL-E 3 |
|
|
59
|
+
| `openai/gpt-image-1` | `gpt-image` | $0.02/image | 1536×1024 | OpenAI GPT Image |
|
|
60
|
+
| `black-forest/flux-1.1-pro`| `flux` | $0.04/image | 1024×1024 | Black Forest Labs |
|
|
61
|
+
|
|
62
|
+
Default model: `google/nano-banana`.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## API Reference
|
|
67
|
+
|
|
68
|
+
### `POST /v1/images/generations`
|
|
69
|
+
|
|
70
|
+
OpenAI-compatible endpoint. Route via ClawRouter proxy (`http://localhost:8402`) for automatic x402 payment handling.
|
|
71
|
+
|
|
72
|
+
**Request body:**
|
|
73
|
+
|
|
74
|
+
| Field | Type | Required | Description |
|
|
75
|
+
| -------- | -------- | -------- | ------------------------------------------------ |
|
|
76
|
+
| `model` | `string` | Yes | Model ID (see table above) |
|
|
77
|
+
| `prompt` | `string` | Yes | Text description of the image to generate |
|
|
78
|
+
| `size` | `string` | No | Image dimensions, e.g. `"1024x1024"` (default) |
|
|
79
|
+
| `n` | `number` | No | Number of images (default: `1`) |
|
|
80
|
+
|
|
81
|
+
**Response:**
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
{
|
|
85
|
+
created: number; // Unix timestamp
|
|
86
|
+
data: Array<{
|
|
87
|
+
url: string; // Publicly hosted image URL
|
|
88
|
+
revised_prompt?: string; // Model's rewritten prompt (dall-e-3 only)
|
|
89
|
+
}>;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `POST /v1/images/image2image`
|
|
94
|
+
|
|
95
|
+
Edit an existing image using AI. Route via ClawRouter proxy (`http://localhost:8402`) for automatic x402 payment handling.
|
|
96
|
+
|
|
97
|
+
**Request body:**
|
|
98
|
+
|
|
99
|
+
| Field | Type | Required | Description |
|
|
100
|
+
| -------- | -------- | -------- | -------------------------------------------------------------- |
|
|
101
|
+
| `model` | `string` | No | Model ID (default: `openai/gpt-image-1`) |
|
|
102
|
+
| `prompt` | `string` | Yes | Text description of the edit to apply |
|
|
103
|
+
| `image` | `string` | Yes | Source image — see **Image input formats** below |
|
|
104
|
+
| `mask` | `string` | No | Mask image (white = area to edit) — same formats as `image` |
|
|
105
|
+
| `size` | `string` | No | Output dimensions, e.g. `"1024x1024"` (default) |
|
|
106
|
+
|
|
107
|
+
**Image input formats** — the `image` and `mask` fields accept any of:
|
|
108
|
+
|
|
109
|
+
| Format | Example | Description |
|
|
110
|
+
| ------------------- | ------------------------------------ | ---------------------------------------------- |
|
|
111
|
+
| Local file path | `"/Users/me/photo.png"` | Absolute path — ClawRouter reads the file |
|
|
112
|
+
| Home-relative path | `"~/photo.png"` | Expands `~` to home directory |
|
|
113
|
+
| HTTP/HTTPS URL | `"https://example.com/photo.png"` | ClawRouter downloads the image automatically |
|
|
114
|
+
| Base64 data URI | `"data:image/png;base64,iVBOR..."` | Passed through directly (no conversion needed) |
|
|
115
|
+
|
|
116
|
+
Supported image formats: **PNG**, **JPG/JPEG**, **WebP**.
|
|
117
|
+
|
|
118
|
+
**Response:**
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
{
|
|
122
|
+
created: number; // Unix timestamp
|
|
123
|
+
data: Array<{
|
|
124
|
+
url: string; // Locally cached image URL (http://localhost:8402/images/...)
|
|
125
|
+
revised_prompt?: string; // Model's rewritten prompt
|
|
126
|
+
}>;
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Code Examples
|
|
133
|
+
|
|
134
|
+
### Image Generation Examples {#image-generation-examples}
|
|
135
|
+
|
|
136
|
+
### curl
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Default model (nano-banana, $0.05)
|
|
140
|
+
curl -X POST http://localhost:8402/v1/images/generations \
|
|
141
|
+
-H "Content-Type: application/json" \
|
|
142
|
+
-d '{
|
|
143
|
+
"model": "google/nano-banana",
|
|
144
|
+
"prompt": "a futuristic city at sunset, cyberpunk style",
|
|
145
|
+
"size": "1024x1024",
|
|
146
|
+
"n": 1
|
|
147
|
+
}'
|
|
148
|
+
|
|
149
|
+
# DALL-E 3 with landscape size ($0.04)
|
|
150
|
+
curl -X POST http://localhost:8402/v1/images/generations \
|
|
151
|
+
-H "Content-Type: application/json" \
|
|
152
|
+
-d '{
|
|
153
|
+
"model": "openai/dall-e-3",
|
|
154
|
+
"prompt": "a serene Japanese garden in autumn",
|
|
155
|
+
"size": "1792x1024",
|
|
156
|
+
"n": 1
|
|
157
|
+
}'
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### TypeScript / Node.js
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
const response = await fetch("http://localhost:8402/v1/images/generations", {
|
|
164
|
+
method: "POST",
|
|
165
|
+
headers: { "Content-Type": "application/json" },
|
|
166
|
+
body: JSON.stringify({
|
|
167
|
+
model: "google/nano-banana",
|
|
168
|
+
prompt: "a golden retriever surfing on a wave",
|
|
169
|
+
size: "1024x1024",
|
|
170
|
+
n: 1,
|
|
171
|
+
}),
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const result = await response.json() as {
|
|
175
|
+
created: number;
|
|
176
|
+
data: Array<{ url: string; revised_prompt?: string }>;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const imageUrl = result.data[0].url;
|
|
180
|
+
console.log(imageUrl); // https://files.catbox.moe/xxx.png
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Python
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
import requests
|
|
187
|
+
|
|
188
|
+
response = requests.post(
|
|
189
|
+
"http://localhost:8402/v1/images/generations",
|
|
190
|
+
json={
|
|
191
|
+
"model": "google/nano-banana",
|
|
192
|
+
"prompt": "a golden retriever surfing on a wave",
|
|
193
|
+
"size": "1024x1024",
|
|
194
|
+
"n": 1,
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
result = response.json()
|
|
199
|
+
image_url = result["data"][0]["url"]
|
|
200
|
+
print(image_url)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### OpenAI SDK (drop-in)
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import OpenAI from "openai";
|
|
207
|
+
|
|
208
|
+
const client = new OpenAI({
|
|
209
|
+
apiKey: "blockrun", // any non-empty string
|
|
210
|
+
baseURL: "http://localhost:8402/v1",
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const response = await client.images.generate({
|
|
214
|
+
model: "google/nano-banana",
|
|
215
|
+
prompt: "a golden retriever surfing on a wave",
|
|
216
|
+
size: "1024x1024",
|
|
217
|
+
n: 1,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
console.log(response.data[0].url);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### startProxy (programmatic)
|
|
224
|
+
|
|
225
|
+
If you're using ClawRouter as a library:
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { startProxy } from "@blockrun/clawrouter";
|
|
229
|
+
|
|
230
|
+
const proxy = await startProxy({ walletKey: process.env.BLOCKRUN_WALLET_KEY! });
|
|
231
|
+
|
|
232
|
+
const response = await fetch(`${proxy.baseUrl}/v1/images/generations`, {
|
|
233
|
+
method: "POST",
|
|
234
|
+
headers: { "Content-Type": "application/json" },
|
|
235
|
+
body: JSON.stringify({
|
|
236
|
+
model: "openai/dall-e-3",
|
|
237
|
+
prompt: "a serene Japanese garden in autumn",
|
|
238
|
+
size: "1792x1024",
|
|
239
|
+
n: 1,
|
|
240
|
+
}),
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
const { data } = await response.json();
|
|
244
|
+
console.log(data[0].url);
|
|
245
|
+
|
|
246
|
+
await proxy.close();
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Image Editing Examples {#image-editing-examples}
|
|
250
|
+
|
|
251
|
+
### curl
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
# Using a local file path (simplest)
|
|
255
|
+
curl -X POST http://localhost:8402/v1/images/image2image \
|
|
256
|
+
-H "Content-Type: application/json" \
|
|
257
|
+
-d '{
|
|
258
|
+
"prompt": "add sunglasses to the person",
|
|
259
|
+
"image": "~/photo.png"
|
|
260
|
+
}'
|
|
261
|
+
|
|
262
|
+
# Using an image URL
|
|
263
|
+
curl -X POST http://localhost:8402/v1/images/image2image \
|
|
264
|
+
-H "Content-Type: application/json" \
|
|
265
|
+
-d '{
|
|
266
|
+
"prompt": "change the background to a sunset beach",
|
|
267
|
+
"image": "https://example.com/photo.png"
|
|
268
|
+
}'
|
|
269
|
+
|
|
270
|
+
# With a mask (inpainting — white = area to edit)
|
|
271
|
+
curl -X POST http://localhost:8402/v1/images/image2image \
|
|
272
|
+
-H "Content-Type: application/json" \
|
|
273
|
+
-d '{
|
|
274
|
+
"prompt": "replace the background with a starry sky",
|
|
275
|
+
"image": "~/photo.png",
|
|
276
|
+
"mask": "~/mask.png"
|
|
277
|
+
}'
|
|
278
|
+
|
|
279
|
+
# With explicit model, size, and base64 data URI
|
|
280
|
+
curl -X POST http://localhost:8402/v1/images/image2image \
|
|
281
|
+
-H "Content-Type: application/json" \
|
|
282
|
+
-d '{
|
|
283
|
+
"model": "openai/gpt-image-1",
|
|
284
|
+
"prompt": "add a crown",
|
|
285
|
+
"image": "data:image/png;base64,iVBOR...",
|
|
286
|
+
"size": "1536x1024"
|
|
287
|
+
}'
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### TypeScript / Node.js
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// ClawRouter reads the file for you — no base64 encoding needed
|
|
294
|
+
const response = await fetch("http://localhost:8402/v1/images/image2image", {
|
|
295
|
+
method: "POST",
|
|
296
|
+
headers: { "Content-Type": "application/json" },
|
|
297
|
+
body: JSON.stringify({
|
|
298
|
+
prompt: "change the background to a starry sky",
|
|
299
|
+
image: "/Users/me/photo.png", // or "~/photo.png" or an HTTPS URL
|
|
300
|
+
}),
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const result = (await response.json()) as {
|
|
304
|
+
created: number;
|
|
305
|
+
data: Array<{ url: string; revised_prompt?: string }>;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
console.log(result.data[0].url); // http://localhost:8402/images/xxx.png
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Python
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
import requests
|
|
315
|
+
|
|
316
|
+
response = requests.post(
|
|
317
|
+
"http://localhost:8402/v1/images/image2image",
|
|
318
|
+
json={
|
|
319
|
+
"prompt": "add a hat to the person",
|
|
320
|
+
"image": "~/photo.png", # or an absolute path or HTTPS URL
|
|
321
|
+
},
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
result = response.json()
|
|
325
|
+
print(result["data"][0]["url"])
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## In-Chat Commands
|
|
331
|
+
|
|
332
|
+
When using ClawRouter with OpenClaw, generate and edit images directly from any conversation:
|
|
333
|
+
|
|
334
|
+
### `/imagegen` — Generate images
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
/imagegen a dog dancing on the beach
|
|
338
|
+
/imagegen --model dall-e-3 a futuristic city at sunset
|
|
339
|
+
/imagegen --model banana-pro --size 2048x2048 mountain landscape
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
| Flag | Default | Description |
|
|
343
|
+
| --------- | ------------- | --------------------- |
|
|
344
|
+
| `--model` | `nano-banana` | Model shorthand or ID |
|
|
345
|
+
| `--size` | `1024x1024` | Image dimensions |
|
|
346
|
+
|
|
347
|
+
### `/img2img` — Edit images
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
/img2img --image ~/photo.png change the background to a starry sky
|
|
351
|
+
/img2img --image ./cat.jpg --mask ./mask.png remove the background
|
|
352
|
+
/img2img --image /tmp/portrait.png --size 1536x1024 add a hat
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
| Flag | Default | Description |
|
|
356
|
+
| --------- | -------------- | ------------------------------------- |
|
|
357
|
+
| `--image` | _(required)_ | Local image file path (supports `~/`) |
|
|
358
|
+
| `--mask` | _(none)_ | Mask image (white = area to edit) |
|
|
359
|
+
| `--model` | `gpt-image-1` | Model to use |
|
|
360
|
+
| `--size` | `1024x1024` | Output size |
|
|
361
|
+
|
|
362
|
+
### Model shorthands
|
|
363
|
+
|
|
364
|
+
| Shorthand | Full ID |
|
|
365
|
+
| ------------- | --------------------------- |
|
|
366
|
+
| `nano-banana` | `google/nano-banana` |
|
|
367
|
+
| `banana-pro` | `google/nano-banana-pro` |
|
|
368
|
+
| `dall-e-3` | `openai/dall-e-3` |
|
|
369
|
+
| `gpt-image` | `openai/gpt-image-1` |
|
|
370
|
+
| `flux` | `black-forest/flux-1.1-pro` |
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Notes
|
|
375
|
+
|
|
376
|
+
- **Local image caching** — All images (generated and edited) are cached locally at `~/.openclaw/blockrun/images/` and served via `http://localhost:8402/images/`. Both base64 data URIs and HTTP URLs from upstream are downloaded and replaced with localhost URLs.
|
|
377
|
+
- **Payment** — Each image costs the listed price in USDC, deducted from your wallet via x402. Make sure your wallet is funded before generating or editing.
|
|
378
|
+
- **No DALL-E content policy bypass** — DALL-E 3 and GPT Image 1 still apply OpenAI's content policy. Use `flux` or `nano-banana` for more flexibility with generation.
|
|
379
|
+
- **Size limits** — Requesting a size larger than the model's max will return an error. Check the table above before setting `--size`.
|
|
380
|
+
- **Image editing** — The `/v1/images/image2image` endpoint currently supports `openai/gpt-image-1` (default). The `image` and `mask` fields accept local file paths (`~/photo.png`, `/abs/path.png`), HTTP/HTTPS URLs, or base64 data URIs. ClawRouter handles file reading and URL downloading automatically. Supported formats: PNG, JPG/JPEG, WebP.
|