@blockrun/clawrouter 0.12.85 → 0.12.87

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.
@@ -18,19 +18,19 @@ BlockRun's answer: just take them.
18
18
 
19
19
  Through [ClawRouter](https://github.com/blockrunai/ClawRouter) — BlockRun's local AI routing proxy — you get zero-cost access to the following:
20
20
 
21
- | Model | Parameters | Context | Reasoning | Best For |
22
- |-------|-----------|---------|-----------|----------|
23
- | **GPT-OSS 120B** | 120B | 128K | — | General chat, summaries, formatting |
24
- | **GPT-OSS 20B** | 20B | 128K | — | Fast lightweight tasks |
25
- | **Nemotron Ultra 253B** | 253B | 131K | ✅ | Complex reasoning, math, analysis |
26
- | **Nemotron 3 Super 120B** | 120B | 131K | ✅ | Balanced reasoning + general |
27
- | **Nemotron Super 49B** | 49B | 131K | ✅ | Quick reasoning, low latency |
28
- | **DeepSeek V3.2** | — | 128K | ✅ | Code generation, technical reasoning |
29
- | **Mistral Large 675B** | 675B | 128K | ✅ | Multilingual, long-form, complex instructions |
30
- | **Qwen3 Coder 480B** | 480B | 128K | — | Professional code generation |
31
- | **Devstral 2 123B** | 123B | 128K | — | Developer tooling, code review |
32
- | **GLM-4.7** | — | 128K | ✅ | Chinese-English bilingual reasoning |
33
- | **Llama 4 Maverick** | — | 128K | ✅ | Meta's latest open-source all-rounder |
21
+ | Model | Parameters | Context | Reasoning | Best For |
22
+ | ------------------------- | ---------- | ------- | --------- | --------------------------------------------- |
23
+ | **GPT-OSS 120B** | 120B | 128K | — | General chat, summaries, formatting |
24
+ | **GPT-OSS 20B** | 20B | 128K | — | Fast lightweight tasks |
25
+ | **Nemotron Ultra 253B** | 253B | 131K | ✅ | Complex reasoning, math, analysis |
26
+ | **Nemotron 3 Super 120B** | 120B | 131K | ✅ | Balanced reasoning + general |
27
+ | **Nemotron Super 49B** | 49B | 131K | ✅ | Quick reasoning, low latency |
28
+ | **DeepSeek V3.2** | — | 128K | ✅ | Code generation, technical reasoning |
29
+ | **Mistral Large 675B** | 675B | 128K | ✅ | Multilingual, long-form, complex instructions |
30
+ | **Qwen3 Coder 480B** | 480B | 128K | — | Professional code generation |
31
+ | **Devstral 2 123B** | 123B | 128K | — | Developer tooling, code review |
32
+ | **GLM-4.7** | — | 128K | ✅ | Chinese-English bilingual reasoning |
33
+ | **Llama 4 Maverick** | — | 128K | ✅ | Meta's latest open-source all-rounder |
34
34
 
35
35
  **Price: $0.00 per million tokens. Input free. Output free. No hidden fees. No daily caps. No trial period.**
36
36
 
@@ -56,30 +56,31 @@ ClawRouter's value proposition isn't just "here are free models." It's **intelli
56
56
 
57
57
  ClawRouter classifies every incoming request into one of four complexity tiers:
58
58
 
59
- | Tier | Typical Tasks | ECO Route (Cheapest) | AUTO Route (Balanced) |
60
- |------|--------------|---------------------|----------------------|
61
- | **SIMPLE** | Formatting, translation, Q&A | 🆓 GPT-OSS 120B (FREE) | GPT-4o Mini |
62
- | **MEDIUM** | Summaries, analysis, general coding | 🆓 DeepSeek V3.2 (FREE) | DeepSeek V3.2 |
63
- | **COMPLEX** | Architecture, complex code | 🆓 Nemotron Ultra 253B (FREE) | Claude Sonnet 4 |
64
- | **REASONING** | Mathematical proofs, multi-step logic | DeepSeek R1 | Claude Opus 4 |
59
+ | Tier | Typical Tasks | ECO Route (Cheapest) | AUTO Route (Balanced) |
60
+ | ------------- | ------------------------------------- | ----------------------------- | --------------------- |
61
+ | **SIMPLE** | Formatting, translation, Q&A | 🆓 GPT-OSS 120B (FREE) | GPT-4o Mini |
62
+ | **MEDIUM** | Summaries, analysis, general coding | 🆓 DeepSeek V3.2 (FREE) | DeepSeek V3.2 |
63
+ | **COMPLEX** | Architecture, complex code | 🆓 Nemotron Ultra 253B (FREE) | Claude Sonnet 4 |
64
+ | **REASONING** | Mathematical proofs, multi-step logic | DeepSeek R1 | Claude Opus 4 |
65
65
 
66
66
  Look at the ECO column. **Three out of four tiers route to free models.** Unless you're doing the hardest reasoning tasks, your daily work costs nothing.
67
67
 
68
68
  ### Real-World Cost Comparison
69
69
 
70
70
  Assume 100 requests per day, distributed roughly as:
71
+
71
72
  - 40% SIMPLE (chat, translation, formatting)
72
73
  - 30% MEDIUM (coding, analysis)
73
74
  - 20% COMPLEX (architecture, deep debugging)
74
75
  - 10% REASONING (math, formal logic)
75
76
 
76
- | Approach | Estimated Monthly Cost |
77
- |----------|----------------------|
78
- | Pure Claude Opus 4 | ~$75–150 |
79
- | Pure GPT-4o | ~$15–30 |
80
- | ClawRouter AUTO mode | ~$5–10 |
81
- | ClawRouter ECO mode | ~$1–3 |
82
- | Manual free model selection | **$0** |
77
+ | Approach | Estimated Monthly Cost |
78
+ | --------------------------- | ---------------------- |
79
+ | Pure Claude Opus 4 | ~$75–150 |
80
+ | Pure GPT-4o | ~$15–30 |
81
+ | ClawRouter AUTO mode | ~$5–10 |
82
+ | ClawRouter ECO mode | ~$1–3 |
83
+ | Manual free model selection | **$0** |
83
84
 
84
85
  **ECO mode saves 92%+ compared to Claude Opus alone.**
85
86
 
@@ -273,4 +274,4 @@ Go build something.
273
274
 
274
275
  ---
275
276
 
276
- *Based on ClawRouter v0.12.84. Model availability may change with future releases. For the latest information, visit [blockrun.ai](https://blockrun.ai).*
277
+ _Based on ClawRouter v0.12.84. Model availability may change with future releases. For the latest information, visit [blockrun.ai](https://blockrun.ai)._
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/clawrouter",
3
- "version": "0.12.85",
3
+ "version": "0.12.87",
4
4
  "description": "Smart LLM router — save 85% on inference costs. 55+ models (11 free), one wallet, x402 micropayments.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -74,9 +74,9 @@
74
74
  "@scure/bip32": "^2.0.1",
75
75
  "@scure/bip39": "^1.5.0",
76
76
  "@solana/kit": "^5.0.0",
77
- "@x402/evm": "^2.7.0",
78
- "@x402/fetch": "^2.7.0",
79
- "@x402/svm": "^2.7.0",
77
+ "@x402/evm": "^2.8.0",
78
+ "@x402/fetch": "^2.8.0",
79
+ "@x402/svm": "^2.8.0",
80
80
  "viem": "^2.39.3"
81
81
  },
82
82
  "peerDependencies": {
@@ -1,80 +1,114 @@
1
1
  ---
2
2
  name: imagegen
3
- description: Generate images via BlockRun's image API. Trigger when the user asks to generate, create, draw, or make an image.
3
+ description: Generate or edit images via BlockRun's image API. Trigger when the user asks to generate, create, draw, make an image — or to edit, modify, change, or retouch an existing image.
4
4
  metadata: { "openclaw": { "emoji": "🖼️", "requires": { "config": ["models.providers.blockrun"] } } }
5
5
  ---
6
6
 
7
- # Image Generation
7
+ # Image Generation & Editing
8
8
 
9
- When the user asks to generate, create, draw, or make an image, generate it by calling ClawRouter's image API directly — no extra setup needed.
9
+ Generate or edit images through ClawRouter. Payment is automatic via x402.
10
10
 
11
- ## How to Generate
11
+ ---
12
+
13
+ ## Generate an Image
12
14
 
13
15
  POST to `http://localhost:8402/v1/images/generations`:
14
16
 
15
17
  ```json
16
18
  {
17
19
  "model": "google/nano-banana",
18
- "prompt": "<user's prompt>",
20
+ "prompt": "a golden retriever surfing on a wave",
19
21
  "size": "1024x1024",
20
22
  "n": 1
21
23
  }
22
24
  ```
23
25
 
24
- The response contains a public image URL:
26
+ Response:
25
27
 
26
28
  ```json
27
29
  {
28
30
  "created": 1741460000,
29
- "data": [{ "url": "https://files.catbox.moe/abc123.png" }]
31
+ "data": [{ "url": "http://localhost:8402/images/abc123.png" }]
30
32
  }
31
33
  ```
32
34
 
33
- Display the image inline in your response:
35
+ Display inline: `![generated image](http://localhost:8402/images/abc123.png)`
34
36
 
35
- ```markdown
36
- ![generated image](https://files.catbox.moe/abc123.png)
37
- ```
37
+ ### Model Selection
38
38
 
39
- ## Model Selection
39
+ | Model | Full ID | Price | Sizes | Best for |
40
+ |-------|---------|-------|-------|----------|
41
+ | `nano-banana` | `google/nano-banana` | $0.05 | 1024×1024, 1216×832, 1024×1792 | Default — fast, cheap, good quality |
42
+ | `banana-pro` | `google/nano-banana-pro` | $0.10 | up to 4096×4096 | High-res, large format |
43
+ | `dall-e-3` | `openai/dall-e-3` | $0.04 | 1024×1024, 1792×1024, 1024×1792 | Photorealistic, complex scenes |
44
+ | `gpt-image` | `openai/gpt-image-1` | $0.02 | 1024×1024, 1536×1024, 1024×1536 | Budget option |
45
+ | `flux` | `black-forest/flux-1.1-pro` | $0.04 | 1024×1024, 1216×832, 832×1216 | Artistic styles, fewer restrictions |
40
46
 
41
- Pick the model based on what the user asks for (or default to `nano-banana`):
47
+ **Choosing a model:**
48
+ - Default → `nano-banana`
49
+ - "high res" / "large" → `banana-pro`
50
+ - "photorealistic" / "dall-e" → `dall-e-3`
51
+ - "artistic" / flexible content → `flux`
42
52
 
43
- | Model shorthand | Full ID | Price | Best for |
44
- | --------------- | --------------------------- | ----- | ----------------------------------- |
45
- | `nano-banana` | `google/nano-banana` | $0.05 | Default — fast, cheap, good quality |
46
- | `banana-pro` | `google/nano-banana-pro` | $0.10 | High-res up to 4096×4096 |
47
- | `dall-e-3` | `openai/dall-e-3` | $0.04 | Photorealistic, complex scenes |
48
- | `gpt-image` | `openai/gpt-image-1` | $0.02 | Budget option |
49
- | `flux` | `black-forest/flux-1.1-pro` | $0.04 | Artistic styles, fewer restrictions |
53
+ **Choosing a size:**
54
+ - Default: `1024x1024`
55
+ - Portrait: `1024x1792`
56
+ - Landscape: `1792x1024` (dall-e-3) or `1216x832` (nano-banana / flux)
57
+ - High-res: `2048x2048` or `4096x4096` with `banana-pro` only
50
58
 
51
- If the user mentions "high res" or "large", use `banana-pro`. If they want "photorealistic" or "dall-e", use `dall-e-3`. Otherwise default to `nano-banana`.
59
+ ---
52
60
 
53
- ## Size Options
61
+ ## Edit an Existing Image
54
62
 
55
- Default is `1024x1024`. Adjust based on user request:
63
+ POST to `http://localhost:8402/v1/images/image2image`:
56
64
 
57
- - Portrait: `1024x1792`
58
- - Landscape: `1792x1024` (dall-e-3) or `1216x832` (nano-banana / flux)
59
- - High-res: up to `4096x4096` with `banana-pro` only
65
+ ```json
66
+ {
67
+ "model": "openai/gpt-image-1",
68
+ "prompt": "make the background a snowy mountain landscape",
69
+ "image": "https://example.com/photo.jpg",
70
+ "size": "1024x1024",
71
+ "n": 1
72
+ }
73
+ ```
60
74
 
61
- ## Example Interactions
75
+ ClawRouter automatically downloads URLs and reads local file paths — pass them directly, no manual base64 conversion needed.
76
+
77
+ Optional `mask` field: a second image (URL or path) that marks which areas to edit (white = edit, black = keep).
78
+
79
+ Response is identical to generation:
80
+
81
+ ```json
82
+ {
83
+ "created": 1741460000,
84
+ "data": [{ "url": "http://localhost:8402/images/xyz456.png", "revised_prompt": "..." }]
85
+ }
86
+ ```
62
87
 
63
- **User:** Draw me a golden retriever surfing on a wave
88
+ **Supported models for editing:** `openai/gpt-image-1` only ($0.02)
64
89
 
65
- → Call `nano-banana` with prompt `"a golden retriever surfing on a wave"`, display the image.
90
+ ---
66
91
 
67
- **User:** Generate a high-res mountain landscape, landscape format
92
+ ## Example Interactions
68
93
 
69
- → Call `banana-pro` with size `1024x1024` (max varies by model), prompt `"mountain landscape"`.
94
+ **User:** Draw me a cyberpunk city at night
95
+ → POST to `/v1/images/generations`, model `nano-banana`, prompt as given.
70
96
 
71
- **User:** Make a cyberpunk city with dall-e
97
+ **User:** Generate a high-res portrait of a samurai
98
+ → POST to `/v1/images/generations`, model `banana-pro`, size `1024x1792`.
72
99
 
73
- → Call `dall-e-3` with prompt `"a futuristic cyberpunk city"`.
100
+ **User:** Edit this photo to add a sunset background: https://example.com/portrait.jpg
101
+ → POST to `/v1/images/image2image`, model `gpt-image`, image = the URL, prompt = "add a warm sunset background".
102
+
103
+ **User:** Change the background in my image to a beach (attaches local file)
104
+ → POST to `/v1/images/image2image`, image = the local file path, prompt describes the change.
105
+
106
+ ---
74
107
 
75
108
  ## Notes
76
109
 
77
110
  - Payment is automatic via x402 — deducted from the user's BlockRun wallet
78
111
  - If the call fails with a payment error, tell the user to fund their wallet at [blockrun.ai](https://blockrun.ai)
79
- - DALL-E 3 applies OpenAI content policy; use `flux` or `nano-banana` for more flexibility
80
- - Google models may return base64 — ClawRouter handles uploading automatically, you'll get a URL back
112
+ - Google models may return base64 internally — ClawRouter uploads automatically and returns a hosted URL
113
+ - DALL-E 3 enforces OpenAI content policy; use `flux` or `nano-banana` for more flexibility
114
+ - Image editing is only available with `gpt-image-1`; generation supports all 5 models
@@ -0,0 +1,169 @@
1
+ ---
2
+ name: predexon
3
+ description: Query prediction market data via BlockRun. Trigger when the user asks about Polymarket, Kalshi, prediction markets, betting odds, smart money positioning, or wants to analyze a prediction market wallet.
4
+ homepage: https://blockrun.ai/partners/predexon
5
+ metadata: { "openclaw": { "emoji": "📊", "requires": { "config": ["models.providers.blockrun"] } } }
6
+ ---
7
+
8
+ # Predexon — Prediction Market Data
9
+
10
+ Real-time prediction market data (Polymarket, Kalshi, dFlow, Binance) via BlockRun's x402 gateway. Payment is automatic — deducted from the user's BlockRun wallet.
11
+
12
+ **All responses are wrapped:** `{ "data": { ... } }` — always read from `response.data`.
13
+
14
+ **Pricing:** GET $0.001 · Wallet analytics / smart money / Binance / matching $0.005
15
+
16
+ ---
17
+
18
+ ## Browse Markets & Events
19
+
20
+ GET `http://localhost:8402/v1/pm/polymarket/events?limit=20`
21
+
22
+ Common params: `limit`, `offset`, `tag` (e.g. `crypto`, `politics`, `sports`)
23
+
24
+ Response fields in `data`:
25
+ - `events[].title` — market name
26
+ - `events[].outcomes` — array of `{ name, price }` (price = implied probability 0–1)
27
+ - `events[].volume` — total volume in USD
28
+ - `events[].endDate` — resolution date
29
+ - `events[].conditionId` — use this for follow-up calls
30
+
31
+ To search by keyword: `GET /v1/pm/polymarket/markets?search=bitcoin&limit=10`
32
+
33
+ Response fields in `data`:
34
+ - `markets[].question` — market question
35
+ - `markets[].conditionId`
36
+ - `markets[].outcomes[].price`
37
+ - `markets[].volumeNum`
38
+
39
+ ---
40
+
41
+ ## Smart Money on a Market
42
+
43
+ Find the `conditionId` first (from events/markets above), then:
44
+
45
+ GET `http://localhost:8402/v1/pm/polymarket/market/{conditionId}/smart-money`
46
+
47
+ Response fields in `data`:
48
+ - `positions[].wallet` — wallet address
49
+ - `positions[].side` — YES or NO
50
+ - `positions[].size` — position size in USD
51
+ - `positions[].pnl` — profit/loss on this position
52
+ - `positions[].winRate` — wallet's historical win rate
53
+
54
+ ---
55
+
56
+ ## Leaderboard
57
+
58
+ GET `http://localhost:8402/v1/pm/polymarket/leaderboard?limit=20`
59
+
60
+ Response fields in `data`:
61
+ - `wallets[].address`
62
+ - `wallets[].profit` — total realized profit in USD
63
+ - `wallets[].volume`
64
+ - `wallets[].winRate`
65
+ - `wallets[].marketsTraded`
66
+
67
+ ---
68
+
69
+ ## Wallet Analysis
70
+
71
+ GET `http://localhost:8402/v1/pm/polymarket/wallet/{walletAddress}`
72
+
73
+ Response fields in `data`:
74
+ - `profit` — total realized profit
75
+ - `volume` — total traded volume
76
+ - `winRate` — fraction of winning trades (0–1)
77
+ - `marketsTraded` — number of distinct markets
78
+ - `currentPositions[]` — open positions
79
+
80
+ For P&L over time: GET `/v1/pm/polymarket/wallet/pnl/{walletAddress}`
81
+ - `data.pnlSeries[]` — `{ date, cumulativePnl }`
82
+ - `data.totalProfit`, `data.totalLoss`
83
+
84
+ ---
85
+
86
+ ## Compare Polymarket vs Kalshi
87
+
88
+ GET `http://localhost:8402/v1/pm/matching-markets?limit=10`
89
+
90
+ Response fields in `data`:
91
+ - `pairs[].polymarketTitle`
92
+ - `pairs[].kalshiTitle`
93
+ - `pairs[].polymarketPrice` — YES price on Polymarket (0–1)
94
+ - `pairs[].kalshiPrice` — YES price on Kalshi (0–1)
95
+ - `pairs[].spread` — price difference (arbitrage signal)
96
+
97
+ ---
98
+
99
+ ## Example Interactions
100
+
101
+ **User:** What are the top prediction markets right now?
102
+ → `GET /v1/pm/polymarket/events?limit=20` — summarize top events with titles, outcomes, and current YES/NO prices.
103
+
104
+ **User:** What's the smart money doing on the 2026 election markets?
105
+ → First `GET /v1/pm/polymarket/markets?search=election&limit=5` to get `conditionId`s, then `GET /v1/pm/polymarket/market/{conditionId}/smart-money` for each. Show top positions, sides, and P&L.
106
+
107
+ **User:** Who are the top Polymarket whales?
108
+ → `GET /v1/pm/polymarket/leaderboard?limit=10` — table with wallet (shortened), profit, win rate, markets traded.
109
+
110
+ **User:** Analyze this wallet: 0xabc...
111
+ → `GET /v1/pm/polymarket/wallet/0xabc...` + `GET /v1/pm/polymarket/wallet/pnl/0xabc...` — summarize trading style, win rate, total P&L, current open positions.
112
+
113
+ **User:** Compare Polymarket vs Kalshi on the Fed rate decision
114
+ → `GET /v1/pm/matching-markets?limit=20` — find the Fed pair, show both prices and the spread.
115
+
116
+ ---
117
+
118
+ ## Full Endpoint Reference
119
+
120
+ All endpoints are GET. Query params go in the URL.
121
+
122
+ | Endpoint | Price | Key params |
123
+ |----------|-------|------------|
124
+ | `/v1/pm/polymarket/events` | $0.001 | `limit`, `offset`, `tag` |
125
+ | `/v1/pm/polymarket/markets` | $0.001 | `search`, `limit`, `offset` |
126
+ | `/v1/pm/polymarket/crypto-updown` | $0.001 | — |
127
+ | `/v1/pm/polymarket/leaderboard` | $0.001 | `limit`, `offset` |
128
+ | `/v1/pm/polymarket/leaderboard/market/{conditionId}` | $0.001 | `limit` |
129
+ | `/v1/pm/polymarket/market/{conditionId}/top-holders` | $0.001 | `limit` |
130
+ | `/v1/pm/polymarket/cohorts/stats` | $0.001 | — |
131
+ | `/v1/pm/polymarket/positions` | $0.001 | `wallet`, `limit` |
132
+ | `/v1/pm/polymarket/trades` | $0.001 | `wallet`, `limit`, `start_ts`, `end_ts` |
133
+ | `/v1/pm/polymarket/orderbooks` | $0.001 | `tokenId`, `limit` |
134
+ | `/v1/pm/polymarket/market-price/{tokenId}` | $0.001 | `startTs`, `endTs` |
135
+ | `/v1/pm/polymarket/candlesticks/{conditionId}` | $0.001 | `period`, `limit` |
136
+ | `/v1/pm/polymarket/volume-chart/{conditionId}` | $0.001 | — |
137
+ | `/v1/pm/polymarket/wallet/{wallet}` | $0.005 | — |
138
+ | `/v1/pm/polymarket/wallet/{wallet}/markets` | $0.005 | `limit` |
139
+ | `/v1/pm/polymarket/wallet/{wallet}/similar` | $0.005 | — |
140
+ | `/v1/pm/polymarket/wallet/pnl/{wallet}` | $0.005 | — |
141
+ | `/v1/pm/polymarket/wallet/positions/{wallet}` | $0.005 | — |
142
+ | `/v1/pm/polymarket/wallet/volume-chart/{wallet}` | $0.005 | — |
143
+ | `/v1/pm/polymarket/wallets/profiles` | $0.005 | `wallets` (comma-separated) |
144
+ | `/v1/pm/polymarket/wallets/filter` | $0.005 | `conditionId`, `side` |
145
+ | `/v1/pm/polymarket/market/{conditionId}/smart-money` | $0.005 | `limit` |
146
+ | `/v1/pm/polymarket/markets/smart-activity` | $0.005 | `limit` |
147
+ | `/v1/pm/kalshi/markets` | $0.001 | `search`, `limit` |
148
+ | `/v1/pm/kalshi/trades` | $0.001 | `limit` |
149
+ | `/v1/pm/kalshi/orderbooks` | $0.001 | `marketId` |
150
+ | `/v1/pm/dflow/trades` | $0.001 | `wallet`, `limit` |
151
+ | `/v1/pm/dflow/wallet/positions/{wallet}` | $0.005 | — |
152
+ | `/v1/pm/dflow/wallet/pnl/{wallet}` | $0.005 | — |
153
+ | `/v1/pm/binance/candles/{symbol}` | $0.005 | `interval`, `limit` |
154
+ | `/v1/pm/binance/ticks/{symbol}` | $0.005 | `limit` |
155
+ | `/v1/pm/matching-markets` | $0.005 | `limit`, `offset` |
156
+ | `/v1/pm/matching-markets/pairs` | $0.005 | — |
157
+ | `/v1/pm/limitless/orderbooks` | $0.001 | `marketId` |
158
+ | `/v1/pm/opinion/orderbooks` | $0.001 | `marketId` |
159
+ | `/v1/pm/predictfun/orderbooks` | $0.001 | `marketId` |
160
+
161
+ ---
162
+
163
+ ## Notes
164
+
165
+ - Payment is automatic via x402 — deducted from the user's BlockRun wallet
166
+ - If payment fails, tell the user to fund their wallet at [blockrun.ai](https://blockrun.ai)
167
+ - Retry once on 502 — Predexon can occasionally be slow
168
+ - Always read from `response.data` — every response is wrapped `{ data: ... }`
169
+ - Synthesize data into plain-language analysis — never dump raw JSON