openclaw-freerouter 2.0.0 → 2.0.1
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 +196 -105
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,121 +1,96 @@
|
|
|
1
|
-
# FreeRouter — OpenClaw
|
|
1
|
+
# FreeRouter — Smart LLM Router for OpenClaw
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Stop overpaying for AI.** Every message to your AI assistant costs money — a simple "hello" shouldn't cost the same as "prove the Riemann hypothesis." FreeRouter automatically routes each request to the right model based on complexity.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## The Problem
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
- 🔥 **Wasted money** — Running Claude Opus ($15/$75 per 1M tokens) for every message, even "what's 2+2?"
|
|
8
|
+
- 🤷 **No control** — Can't switch models mid-conversation without editing config files and restarting
|
|
9
|
+
- 📊 **Blind routing** — Your AI shows "freerouter/auto" instead of telling you which model actually answered
|
|
10
|
+
- 🔧 **Complex setup** — Existing routers need separate servers, Docker, complex infra
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
openclaw plugins install /path/to/freerouter-plugin
|
|
13
|
-
```
|
|
12
|
+
## The Solution
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
FreeRouter is an OpenClaw plugin that:
|
|
15
|
+
- **Classifies every request in <1ms** using a 14-dimension weighted scorer (no LLM needed for classification)
|
|
16
|
+
- **Routes to the cheapest model that can handle it** — Kimi for "hello", Opus for architecture design
|
|
17
|
+
- **Reports the real model name** — You see `anthropic/claude-opus-4-6`, not `freerouter/auto`
|
|
18
|
+
- **Lets you override anytime** — Just say "use opus" in plain English
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
## Install
|
|
18
21
|
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
agents: {
|
|
23
|
-
defaults: {
|
|
24
|
-
model: { primary: "freerouter/auto" }
|
|
25
|
-
}
|
|
26
|
-
},
|
|
22
|
+
```bash
|
|
23
|
+
openclaw plugins install openclaw-freerouter
|
|
24
|
+
```
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
providers: {
|
|
30
|
-
freerouter: {
|
|
31
|
-
baseUrl: "http://127.0.0.1:18801/v1",
|
|
32
|
-
api: "openai-completions"
|
|
33
|
-
}
|
|
34
|
-
},
|
|
26
|
+
Then run the setup wizard:
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
freerouter: {
|
|
40
|
-
enabled: true,
|
|
41
|
-
config: {
|
|
42
|
-
port: 18801, // HTTP proxy port (0 = disabled)
|
|
43
|
-
host: "127.0.0.1", // Bind address
|
|
44
|
-
|
|
45
|
-
// Customize which models handle each tier
|
|
46
|
-
tiers: {
|
|
47
|
-
SIMPLE: { primary: "kimi-coding/kimi-for-coding", fallback: ["anthropic/claude-haiku-4-5"] },
|
|
48
|
-
MEDIUM: { primary: "anthropic/claude-sonnet-4-5", fallback: ["anthropic/claude-opus-4-6"] },
|
|
49
|
-
COMPLEX: { primary: "anthropic/claude-opus-4-6", fallback: [] },
|
|
50
|
-
REASONING: { primary: "anthropic/claude-opus-4-6", fallback: [] }
|
|
51
|
-
},
|
|
28
|
+
```bash
|
|
29
|
+
openclaw freerouter setup
|
|
30
|
+
```
|
|
52
31
|
|
|
53
|
-
|
|
54
|
-
thinking: {
|
|
55
|
-
adaptive: ["claude-opus-4-6"],
|
|
56
|
-
enabled: { models: ["claude-sonnet-4-5"], budget: 4096 }
|
|
57
|
-
},
|
|
32
|
+
Or configure manually — see [Configuration](#configure) below.
|
|
58
33
|
|
|
59
|
-
|
|
60
|
-
defaultTier: "MEDIUM"
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
```
|
|
34
|
+
## Switch Models Anytime
|
|
67
35
|
|
|
68
|
-
|
|
36
|
+
The killer feature: **switch models using natural language, slash commands, or session locks.**
|
|
69
37
|
|
|
70
|
-
|
|
71
|
-
2. FreeRouter's HTTP proxy receives it
|
|
72
|
-
3. The 14-dimension classifier scores the request in <1ms
|
|
73
|
-
4. Routes to the best model for the task (e.g., Kimi for simple, Opus for reasoning)
|
|
74
|
-
5. Forwards to the real provider API
|
|
75
|
-
6. **Returns the actual model name** (e.g., `anthropic/claude-opus-4-6`) so OpenClaw displays what's really running
|
|
38
|
+
### Just Say It (Natural Language)
|
|
76
39
|
|
|
77
|
-
|
|
40
|
+
No slash commands needed. Just talk:
|
|
78
41
|
|
|
79
|
-
|
|
|
80
|
-
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
42
|
+
| What you say | What happens |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `use opus` | Switches to Claude Opus for this message |
|
|
45
|
+
| `switch to sonnet` | Switches to Claude Sonnet |
|
|
46
|
+
| `try kimi` | Switches to Kimi |
|
|
47
|
+
| `let's use opus` | Switches to Opus |
|
|
48
|
+
| `please use sonnet` | Switches to Sonnet |
|
|
49
|
+
| `can you use haiku` | Switches to Haiku |
|
|
50
|
+
| `use opus: explain quantum computing` | Uses Opus for this specific prompt |
|
|
51
|
+
| `use opus, what is 2+2?` | Same — model + prompt in one message |
|
|
52
|
+
| `go back to auto` | Return to automatic routing |
|
|
85
53
|
|
|
86
|
-
|
|
54
|
+
### Lock a Model for the Whole Session
|
|
87
55
|
|
|
88
|
-
|
|
56
|
+
When you know the task is important and you want Opus (or any model) for everything:
|
|
89
57
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
58
|
+
| What you say | What happens |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `use opus for this session` | 🔒 Locks ALL messages to Opus |
|
|
61
|
+
| `switch to sonnet from now on` | 🔒 Locks to Sonnet |
|
|
62
|
+
| `stick with opus` | 🔒 Locks to Opus |
|
|
63
|
+
| `keep using sonnet` | 🔒 Locks to Sonnet |
|
|
64
|
+
| `/lock opus` | 🔒 Same thing, slash command |
|
|
65
|
+
| `/unlock` | 🔓 Back to auto-routing |
|
|
66
|
+
| `/lock status` | Shows current lock state |
|
|
95
67
|
|
|
96
|
-
|
|
68
|
+
Session locks expire after 4 hours of inactivity.
|
|
97
69
|
|
|
98
|
-
|
|
70
|
+
### When FreeRouter Isn't Sure
|
|
99
71
|
|
|
100
|
-
|
|
101
|
-
- `/max Prove the Riemann hypothesis` → REASONING tier
|
|
102
|
-
- `[reasoning] Analyze this code...` → REASONING tier
|
|
72
|
+
If your request is ambiguous, FreeRouter asks before switching:
|
|
103
73
|
|
|
104
|
-
|
|
74
|
+
> **You:** "opus please"
|
|
75
|
+
> **FreeRouter:** 🤔 Did you want to switch to **anthropic/claude-opus-4-6**? Reply **yes** or **no**.
|
|
76
|
+
> **You:** "yes"
|
|
77
|
+
> **FreeRouter:** ✅ Confirmed!
|
|
105
78
|
|
|
106
|
-
|
|
79
|
+
This prevents accidental switches when you're just talking *about* a model.
|
|
107
80
|
|
|
108
|
-
|
|
109
|
-
- `/lock sonnet` → 🔒 All messages use Sonnet
|
|
110
|
-
- `/lock simple` → 🔒 Lock to SIMPLE tier's primary model
|
|
111
|
-
- `/lock anthropic/claude-opus-4-6` → 🔒 Full model ID
|
|
112
|
-
- `/unlock` → 🔓 Return to auto-routing
|
|
113
|
-
- `/lock auto` → 🔓 Same as unlock
|
|
114
|
-
- `/lock status` → Show current lock state
|
|
81
|
+
### Slash Commands (Power Users)
|
|
115
82
|
|
|
116
|
-
|
|
83
|
+
| Command | Effect |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `/opus What is 2+2?` | Per-prompt: Opus for this message only |
|
|
86
|
+
| `/sonnet Write a poem` | Per-prompt: Sonnet |
|
|
87
|
+
| `/kimi Quick answer` | Per-prompt: Kimi |
|
|
88
|
+
| `/haiku Translate this` | Per-prompt: Haiku |
|
|
89
|
+
| `/simple What is 2+2?` | Per-prompt: use SIMPLE tier model |
|
|
90
|
+
| `/max Prove this theorem` | Per-prompt: use REASONING tier model |
|
|
91
|
+
| `[opus] Deep analysis` | Bracket syntax (same as /opus) |
|
|
117
92
|
|
|
118
|
-
### Supported Aliases
|
|
93
|
+
### Supported Model Aliases
|
|
119
94
|
|
|
120
95
|
| Alias | Model |
|
|
121
96
|
|-------|-------|
|
|
@@ -125,37 +100,153 @@ Session locks expire after 4 hours of inactivity.
|
|
|
125
100
|
| `haiku`, `haiku-4`, `haiku-4.5` | anthropic/claude-haiku-4-5 |
|
|
126
101
|
| `kimi`, `kimi-k2`, `k2.5` | kimi-coding/kimi-for-coding |
|
|
127
102
|
|
|
128
|
-
##
|
|
103
|
+
## How Routing Works
|
|
104
|
+
|
|
105
|
+
1. You send a message → OpenClaw forwards to FreeRouter
|
|
106
|
+
2. FreeRouter's 14-dimension classifier scores the request in **<1ms** (0.035ms average)
|
|
107
|
+
3. Based on the score, it picks the best tier:
|
|
129
108
|
|
|
130
|
-
|
|
109
|
+
| Tier | Default Model | Use Case | Cost |
|
|
110
|
+
|------|--------------|----------|------|
|
|
111
|
+
| SIMPLE | Kimi K2.5 | Quick lookups, translations, "hello" | $0.50/1M |
|
|
112
|
+
| MEDIUM | Claude Sonnet 4.5 | Code, creative writing, moderate tasks | $3/$15/1M |
|
|
113
|
+
| COMPLEX | Claude Opus 4.6 | Architecture, deep analysis | $15/$75/1M |
|
|
114
|
+
| REASONING | Claude Opus 4.6 | Proofs, formal logic, step-by-step | $15/$75/1M |
|
|
115
|
+
|
|
116
|
+
4. Forwards to the real provider API (Anthropic, Kimi, OpenAI, etc.)
|
|
117
|
+
5. Returns the response with the **actual model name** — not "freerouter/auto"
|
|
118
|
+
|
|
119
|
+
### Scoring Dimensions
|
|
120
|
+
|
|
121
|
+
The classifier evaluates 14 weighted dimensions without calling any LLM:
|
|
131
122
|
- Token count, code presence, reasoning markers, technical terms
|
|
132
123
|
- Creative markers, simple indicators, multi-step patterns
|
|
133
124
|
- Question complexity, imperative verbs, constraints
|
|
134
125
|
- Output format, references, negation, domain specificity
|
|
135
|
-
- Agentic task indicators
|
|
126
|
+
- Agentic task indicators (multi-tool, multi-step workflows)
|
|
127
|
+
|
|
128
|
+
Supports multilingual classification: English, Chinese, Japanese, Russian, German, Vietnamese, Arabic, Korean, and more.
|
|
129
|
+
|
|
130
|
+
## Configure
|
|
131
|
+
|
|
132
|
+
After install, add to your `openclaw.json`:
|
|
133
|
+
|
|
134
|
+
```json5
|
|
135
|
+
{
|
|
136
|
+
// 1. Set FreeRouter as your default model
|
|
137
|
+
"agents": {
|
|
138
|
+
"defaults": {
|
|
139
|
+
"model": {
|
|
140
|
+
"primary": "freerouter/freerouter/auto",
|
|
141
|
+
"fallbacks": ["anthropic/claude-opus-4-6"]
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
// 2. Add FreeRouter as a provider
|
|
147
|
+
"providers": {
|
|
148
|
+
"freerouter": {
|
|
149
|
+
"baseUrl": "http://127.0.0.1:18801/v1",
|
|
150
|
+
"api": "openai-completions"
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
// 3. Plugin config
|
|
155
|
+
"plugins": {
|
|
156
|
+
"entries": {
|
|
157
|
+
"freerouter": {
|
|
158
|
+
"enabled": true,
|
|
159
|
+
"config": {
|
|
160
|
+
"port": 18801,
|
|
161
|
+
"host": "127.0.0.1",
|
|
162
|
+
"tiers": {
|
|
163
|
+
"SIMPLE": { "primary": "kimi-coding/kimi-for-coding", "fallback": ["anthropic/claude-haiku-4-5"] },
|
|
164
|
+
"MEDIUM": { "primary": "anthropic/claude-sonnet-4-5", "fallback": ["anthropic/claude-opus-4-6"] },
|
|
165
|
+
"COMPLEX": { "primary": "anthropic/claude-opus-4-6", "fallback": [] },
|
|
166
|
+
"REASONING": { "primary": "anthropic/claude-opus-4-6", "fallback": [] }
|
|
167
|
+
},
|
|
168
|
+
"thinking": {
|
|
169
|
+
"adaptive": ["claude-opus-4-6"],
|
|
170
|
+
"enabled": { "models": ["claude-sonnet-4-5"], "budget": 4096 }
|
|
171
|
+
},
|
|
172
|
+
"defaultTier": "MEDIUM"
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Then restart: `openclaw gateway restart`
|
|
181
|
+
|
|
182
|
+
## CLI Commands
|
|
183
|
+
|
|
184
|
+
| Command | Description |
|
|
185
|
+
|---|---|
|
|
186
|
+
| `openclaw freerouter status` | Show config, tier mapping, and live stats |
|
|
187
|
+
| `openclaw freerouter setup` | Interactive setup wizard |
|
|
188
|
+
| `openclaw freerouter test` | Quick 5-query classification smoke test |
|
|
189
|
+
| `openclaw freerouter doctor` | Diagnose issues (port conflicts, missing config, etc.) |
|
|
190
|
+
| `openclaw freerouter port <n>` | Change the proxy port |
|
|
191
|
+
| `openclaw freerouter reset` | Show default config for recovery |
|
|
192
|
+
|
|
193
|
+
### Chat Commands
|
|
194
|
+
|
|
195
|
+
| Command | Description |
|
|
196
|
+
|---|---|
|
|
197
|
+
| `/freerouter` | Show routing stats in chat |
|
|
198
|
+
| `/freerouter-doctor` | Quick health check |
|
|
136
199
|
|
|
137
200
|
## Port Conflicts
|
|
138
201
|
|
|
139
|
-
If port 18801 is in use, change it
|
|
202
|
+
If port 18801 is in use, change it:
|
|
140
203
|
|
|
141
204
|
```json5
|
|
142
|
-
{ plugins: { entries: { freerouter: { config: { port: 18802 } } } } }
|
|
205
|
+
{ "plugins": { "entries": { "freerouter": { "config": { "port": 18802 } } } } }
|
|
143
206
|
```
|
|
144
207
|
|
|
145
|
-
Set `port: 0` to disable the HTTP proxy entirely.
|
|
208
|
+
Set `"port": 0` to disable the HTTP proxy entirely.
|
|
209
|
+
|
|
210
|
+
## Troubleshooting
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Check if everything is working
|
|
214
|
+
openclaw freerouter doctor
|
|
146
215
|
|
|
147
|
-
|
|
216
|
+
# Quick classification test
|
|
217
|
+
openclaw freerouter test
|
|
148
218
|
|
|
149
|
-
|
|
150
|
-
|
|
219
|
+
# Reset to defaults
|
|
220
|
+
openclaw freerouter reset
|
|
221
|
+
```
|
|
151
222
|
|
|
152
223
|
## Response Headers
|
|
153
224
|
|
|
154
|
-
Every proxied response includes:
|
|
155
|
-
- `X-FreeRouter-Model` — Actual model used
|
|
156
|
-
- `X-FreeRouter-Tier` — Classification tier
|
|
225
|
+
Every proxied response includes metadata headers:
|
|
226
|
+
- `X-FreeRouter-Model` — Actual model used (e.g., `anthropic/claude-opus-4-6`)
|
|
227
|
+
- `X-FreeRouter-Tier` — Classification tier (SIMPLE/MEDIUM/COMPLEX/REASONING)
|
|
157
228
|
- `X-FreeRouter-Thinking` — Thinking mode (off/adaptive/enabled)
|
|
158
|
-
- `X-FreeRouter-Reasoning` —
|
|
229
|
+
- `X-FreeRouter-Reasoning` — Why this model was chosen
|
|
230
|
+
|
|
231
|
+
## API Endpoints
|
|
232
|
+
|
|
233
|
+
The HTTP proxy exposes:
|
|
234
|
+
- `POST /v1/chat/completions` — OpenAI-compatible chat endpoint
|
|
235
|
+
- `GET /v1/models` — List available models
|
|
236
|
+
- `GET /health` — Health check
|
|
237
|
+
- `GET /stats` — Routing statistics
|
|
238
|
+
- `GET /sessions/locks` — Active session locks
|
|
239
|
+
- `DELETE /sessions/locks` — Clear all session locks
|
|
240
|
+
|
|
241
|
+
## Tests
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
npm test # Runs all 212 tests
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
- `test-freerouter.mjs` — Classification, multilingual, edge cases, performance
|
|
248
|
+
- `test-resilience.mjs` — Fallback chains, bad configs, recovery, port conflicts
|
|
249
|
+
- `test-overrides.mjs` — Model overrides, session locks, natural language switching
|
|
159
250
|
|
|
160
251
|
## License
|
|
161
252
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-freerouter",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
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": {
|
|
7
|
-
"extensions": [
|
|
7
|
+
"extensions": [
|
|
8
|
+
"./src/index.ts"
|
|
9
|
+
]
|
|
8
10
|
},
|
|
9
11
|
"main": "src/index.ts",
|
|
10
12
|
"scripts": {
|