openclaw-freerouter 2.0.1 → 2.1.0
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 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/cli.ts +4 -4
- package/src/index.ts +2 -2
- package/src/service.ts +5 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
- 🔥 **Wasted money** — Running Claude Opus ($15/$75 per 1M tokens) for every message, even "what's 2+2?"
|
|
8
8
|
- 🤷 **No control** — Can't switch models mid-conversation without editing config files and restarting
|
|
9
9
|
- 📊 **Blind routing** — Your AI shows "freerouter/auto" instead of telling you which model actually answered
|
|
10
|
+
- 🧠 **No adaptive thinking** — OpenClaw's built-in thinking levels (`/think low`, `/think high`) are just prompt hints. Anthropic deprecated manual thinking for Opus 4.6 — it now requires the native `thinking: { type: "adaptive" }` API parameter, which OpenClaw doesn't send
|
|
10
11
|
- 🔧 **Complex setup** — Existing routers need separate servers, Docker, complex infra
|
|
11
12
|
|
|
12
13
|
## The Solution
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
FreeRouter is an OpenClaw plugin that:
|
|
15
16
|
- **Classifies every request in <1ms** using a 14-dimension weighted scorer (no LLM needed for classification)
|
|
16
17
|
- **Routes to the cheapest model that can handle it** — Kimi for "hello", Opus for architecture design
|
|
18
|
+
- **Sends native adaptive thinking** — Automatically passes `thinking: { type: "adaptive" }` to Anthropic's API for Opus 4.6, and `thinking: { type: "enabled", budget_tokens: N }` for Sonnet. No prompt hacks — real API-level thinking control that OpenClaw doesn't support natively
|
|
17
19
|
- **Reports the real model name** — You see `anthropic/claude-opus-4-6`, not `freerouter/auto`
|
|
18
20
|
- **Lets you override anytime** — Just say "use opus" in plain English
|
|
19
21
|
|
|
@@ -100,6 +102,36 @@ This prevents accidental switches when you're just talking *about* a model.
|
|
|
100
102
|
| `haiku`, `haiku-4`, `haiku-4.5` | anthropic/claude-haiku-4-5 |
|
|
101
103
|
| `kimi`, `kimi-k2`, `k2.5` | kimi-coding/kimi-for-coding |
|
|
102
104
|
|
|
105
|
+
## Adaptive Thinking (Native API-Level)
|
|
106
|
+
|
|
107
|
+
This is a key reason FreeRouter exists.
|
|
108
|
+
|
|
109
|
+
**The problem:** OpenClaw's built-in `/think low|medium|high` commands are prompt-level hints — they add text like "think harder" to your prompt. This is unreliable and doesn't use Anthropic's actual thinking API. Worse, **Anthropic deprecated manual thinking (`type: "enabled"`) for Opus 4.6** — it now only supports `type: "adaptive"`, where the model decides how much to think based on the task.
|
|
110
|
+
|
|
111
|
+
**What FreeRouter does:** Sends the real `thinking` parameter directly to Anthropic's API:
|
|
112
|
+
|
|
113
|
+
| Model | Thinking Mode | What's Sent |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| Claude Opus 4.6 | **Adaptive** (always) | `thinking: { type: "adaptive" }` |
|
|
116
|
+
| Claude Sonnet 4.5 | Enabled with budget | `thinking: { type: "enabled", budget_tokens: 4096 }` |
|
|
117
|
+
| Others (Kimi, Haiku) | Off | No thinking parameter |
|
|
118
|
+
|
|
119
|
+
**Why this matters:**
|
|
120
|
+
- Adaptive thinking lets Opus 4.6 decide how much reasoning it needs — simple questions get quick answers, complex proofs get deep thinking chains
|
|
121
|
+
- You get the full benefit of Claude's extended thinking without managing budgets
|
|
122
|
+
- The `X-FreeRouter-Thinking` response header tells you exactly which thinking mode was used
|
|
123
|
+
|
|
124
|
+
Configure in your plugin config:
|
|
125
|
+
```json5
|
|
126
|
+
"thinking": {
|
|
127
|
+
"adaptive": ["claude-opus-4-6"], // Models that use adaptive (always-on)
|
|
128
|
+
"enabled": {
|
|
129
|
+
"models": ["claude-sonnet-4-5"], // Models that get explicit thinking
|
|
130
|
+
"budget": 4096 // Token budget for thinking
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
103
135
|
## How Routing Works
|
|
104
136
|
|
|
105
137
|
1. You send a message → OpenClaw forwards to FreeRouter
|
|
@@ -154,7 +186,7 @@ After install, add to your `openclaw.json`:
|
|
|
154
186
|
// 3. Plugin config
|
|
155
187
|
"plugins": {
|
|
156
188
|
"entries": {
|
|
157
|
-
"freerouter": {
|
|
189
|
+
"openclaw-freerouter": {
|
|
158
190
|
"enabled": true,
|
|
159
191
|
"config": {
|
|
160
192
|
"port": 18801,
|
|
@@ -202,7 +234,7 @@ Then restart: `openclaw gateway restart`
|
|
|
202
234
|
If port 18801 is in use, change it:
|
|
203
235
|
|
|
204
236
|
```json5
|
|
205
|
-
{ "plugins": { "entries": { "freerouter": { "config": { "port": 18802 } } } } }
|
|
237
|
+
{ "plugins": { "entries": { "openclaw-freerouter": { "config": { "port": 18802 } } } } }
|
|
206
238
|
```
|
|
207
239
|
|
|
208
240
|
Set `"port": 0` to disable the HTTP proxy entirely.
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"id": "freerouter",
|
|
2
|
+
"id": "openclaw-freerouter",
|
|
3
3
|
"name": "FreeRouter",
|
|
4
4
|
"version": "2.0.0",
|
|
5
5
|
"description": "Smart LLM router — classify requests and route to the best model using your own API keys. 14-dimension weighted scoring, <1ms classification, configurable tiers.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-freerouter",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Smart LLM router plugin for OpenClaw — classify requests and route to the best model using your own API keys. 14-dimension scoring, <1ms classification, per-prompt/session model switching.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"openclaw": {
|
package/src/cli.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { buildPricingMap } from "./models.js";
|
|
|
16
16
|
export function registerCli(api: any) {
|
|
17
17
|
const logger = api.logger ?? console;
|
|
18
18
|
|
|
19
|
-
const getPluginConfig = () => api.config?.plugins?.entries?.freerouter?.config ?? {};
|
|
19
|
+
const getPluginConfig = () => api.config?.plugins?.entries?.["openclaw-freerouter"]?.config ?? {};
|
|
20
20
|
|
|
21
21
|
api.registerCli(
|
|
22
22
|
({ program }: any) => {
|
|
@@ -162,8 +162,8 @@ export function registerCli(api: any) {
|
|
|
162
162
|
enabled: { models: ["claude-sonnet-4-5"], budget: 4096 },
|
|
163
163
|
},
|
|
164
164
|
}, null, 2));
|
|
165
|
-
console.log(
|
|
166
|
-
console.log(
|
|
165
|
+
console.log('\n Copy this into plugins.entries["openclaw-freerouter"].config in openclaw.json');
|
|
166
|
+
console.log(' Or run: openclaw config set plugins.entries["openclaw-freerouter"].config \'{...}\'');
|
|
167
167
|
console.log();
|
|
168
168
|
});
|
|
169
169
|
|
|
@@ -335,7 +335,7 @@ export function registerCli(api: any) {
|
|
|
335
335
|
|
|
336
336
|
Step 1: Add this to your openclaw.json under "plugins.entries":
|
|
337
337
|
|
|
338
|
-
"freerouter": {
|
|
338
|
+
"openclaw-freerouter": {
|
|
339
339
|
"enabled": true,
|
|
340
340
|
"config": ${JSON.stringify(pluginConfig, null, 6).split("\n").map((l, i) => i === 0 ? l : " " + l).join("\n")}
|
|
341
341
|
}
|
package/src/index.ts
CHANGED
|
@@ -22,7 +22,7 @@ export const id = "freerouter";
|
|
|
22
22
|
export default function register(api: any) {
|
|
23
23
|
const logger = api.logger ?? console;
|
|
24
24
|
const getPluginConfig = () => {
|
|
25
|
-
const cfg = api.config?.plugins?.entries?.freerouter?.config ?? {};
|
|
25
|
+
const cfg = api.config?.plugins?.entries?.["openclaw-freerouter"]?.config ?? {};
|
|
26
26
|
return cfg;
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -55,7 +55,7 @@ export default function register(api: any) {
|
|
|
55
55
|
server.on("error", (err: any) => {
|
|
56
56
|
if (err.code === "EADDRINUSE") {
|
|
57
57
|
logger.error(`[freerouter] Port ${port} is already in use. Run: openclaw freerouter doctor`);
|
|
58
|
-
logger.error(`[freerouter] To change port: set plugins.entries
|
|
58
|
+
logger.error(`[freerouter] To change port: set plugins.entries["openclaw-freerouter"].config.port in openclaw.json`);
|
|
59
59
|
} else {
|
|
60
60
|
logger.error(`[freerouter] Server error: ${err.message}`);
|
|
61
61
|
}
|
package/src/service.ts
CHANGED
|
@@ -624,11 +624,15 @@ export function createProxyServer(options: ProxyOptions): { server: Server; stat
|
|
|
624
624
|
}
|
|
625
625
|
|
|
626
626
|
// Determine thinking mode
|
|
627
|
+
// Opus 4.6 REQUIRES adaptive thinking — manual mode is deprecated by Anthropic
|
|
628
|
+
// Other models can use enabled(budget) for explicit thinking control
|
|
627
629
|
const thinkingCfg = pluginConfig.thinking as any;
|
|
628
630
|
const adaptivePatterns = thinkingCfg?.adaptive ?? ["claude-opus-4-6"];
|
|
629
631
|
const enabledCfg = thinkingCfg?.enabled;
|
|
630
632
|
|
|
631
|
-
if (adaptivePatterns.some((p: string) => routedModel.includes(p))
|
|
633
|
+
if (adaptivePatterns.some((p: string) => routedModel.includes(p))) {
|
|
634
|
+
// Adaptive thinking models (e.g., Opus 4.6) — always use adaptive
|
|
635
|
+
// Anthropic deprecated manual thinking for Opus 4.6
|
|
632
636
|
thinkingMode = "adaptive";
|
|
633
637
|
} else if (enabledCfg?.models?.some((p: string) => routedModel.includes(p))) {
|
|
634
638
|
thinkingMode = `enabled(${enabledCfg.budget ?? 4096})`;
|