@blockrun/clawrouter 0.5.9 → 0.6.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 +42 -457
- package/dist/index.js +103 -72
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/scripts/reinstall.sh +177 -0
- package/scripts/uninstall.sh +135 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/clawrouter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Smart LLM router — save 78% on inference costs. 30+ models, one wallet, x402 micropayments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"dist",
|
|
21
|
+
"scripts",
|
|
21
22
|
"openclaw.plugin.json"
|
|
22
23
|
],
|
|
23
24
|
"scripts": {
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
echo "🦞 ClawRouter Reinstall"
|
|
5
|
+
echo ""
|
|
6
|
+
|
|
7
|
+
# 1. Remove plugin files
|
|
8
|
+
echo "→ Removing plugin files..."
|
|
9
|
+
rm -rf ~/.openclaw/extensions/clawrouter
|
|
10
|
+
|
|
11
|
+
# 2. Clean config entries
|
|
12
|
+
echo "→ Cleaning config entries..."
|
|
13
|
+
node -e "
|
|
14
|
+
const f = require('os').homedir() + '/.openclaw/openclaw.json';
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
if (!fs.existsSync(f)) {
|
|
17
|
+
console.log(' No openclaw.json found, skipping');
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let c;
|
|
22
|
+
try {
|
|
23
|
+
c = JSON.parse(fs.readFileSync(f, 'utf8'));
|
|
24
|
+
} catch (err) {
|
|
25
|
+
const backupPath = f + '.corrupt.' + Date.now();
|
|
26
|
+
console.error(' ERROR: Invalid JSON in openclaw.json');
|
|
27
|
+
console.error(' ' + err.message);
|
|
28
|
+
try {
|
|
29
|
+
fs.copyFileSync(f, backupPath);
|
|
30
|
+
console.log(' Backed up to: ' + backupPath);
|
|
31
|
+
} catch {}
|
|
32
|
+
console.log(' Skipping config cleanup...');
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Clean plugin entries
|
|
37
|
+
if (c.plugins?.entries?.clawrouter) delete c.plugins.entries.clawrouter;
|
|
38
|
+
if (c.plugins?.installs?.clawrouter) delete c.plugins.installs.clawrouter;
|
|
39
|
+
// Clean plugins.allow (removes stale clawrouter reference)
|
|
40
|
+
if (Array.isArray(c.plugins?.allow)) {
|
|
41
|
+
c.plugins.allow = c.plugins.allow.filter(p => p !== 'clawrouter' && p !== '@blockrun/clawrouter');
|
|
42
|
+
}
|
|
43
|
+
fs.writeFileSync(f, JSON.stringify(c, null, 2));
|
|
44
|
+
console.log(' Config cleaned');
|
|
45
|
+
"
|
|
46
|
+
|
|
47
|
+
# 3. Kill old proxy
|
|
48
|
+
echo "→ Stopping old proxy..."
|
|
49
|
+
lsof -ti :8402 | xargs kill -9 2>/dev/null || true
|
|
50
|
+
|
|
51
|
+
# 3.1. Remove stale models.json so it gets regenerated with apiKey
|
|
52
|
+
echo "→ Cleaning models cache..."
|
|
53
|
+
rm -f ~/.openclaw/agents/main/agent/models.json 2>/dev/null || true
|
|
54
|
+
|
|
55
|
+
# 4. Reinstall
|
|
56
|
+
echo "→ Installing ClawRouter..."
|
|
57
|
+
openclaw plugins install @blockrun/clawrouter
|
|
58
|
+
|
|
59
|
+
# 5. Inject auth profile (ensures blockrun provider is recognized)
|
|
60
|
+
echo "→ Injecting auth profile..."
|
|
61
|
+
node -e "
|
|
62
|
+
const os = require('os');
|
|
63
|
+
const fs = require('fs');
|
|
64
|
+
const path = require('path');
|
|
65
|
+
const authDir = path.join(os.homedir(), '.openclaw', 'agents', 'main', 'agent');
|
|
66
|
+
const authPath = path.join(authDir, 'auth-profiles.json');
|
|
67
|
+
|
|
68
|
+
// Create directory if needed
|
|
69
|
+
fs.mkdirSync(authDir, { recursive: true });
|
|
70
|
+
|
|
71
|
+
// Load or create auth-profiles.json with correct OpenClaw format
|
|
72
|
+
let store = { version: 1, profiles: {} };
|
|
73
|
+
if (fs.existsSync(authPath)) {
|
|
74
|
+
try {
|
|
75
|
+
const existing = JSON.parse(fs.readFileSync(authPath, 'utf8'));
|
|
76
|
+
// Migrate if old format (no version field)
|
|
77
|
+
if (existing.version && existing.profiles) {
|
|
78
|
+
store = existing;
|
|
79
|
+
} else {
|
|
80
|
+
// Old format - keep version/profiles structure, old data is discarded
|
|
81
|
+
store = { version: 1, profiles: {} };
|
|
82
|
+
}
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.log(' Warning: Could not parse auth-profiles.json, creating fresh');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Inject blockrun auth if missing (OpenClaw format: profiles['provider:profileId'])
|
|
89
|
+
const profileKey = 'blockrun:default';
|
|
90
|
+
if (!store.profiles[profileKey]) {
|
|
91
|
+
store.profiles[profileKey] = {
|
|
92
|
+
type: 'api_key',
|
|
93
|
+
provider: 'blockrun',
|
|
94
|
+
key: 'x402-proxy-handles-auth'
|
|
95
|
+
};
|
|
96
|
+
fs.writeFileSync(authPath, JSON.stringify(store, null, 2));
|
|
97
|
+
console.log(' Auth profile created');
|
|
98
|
+
} else {
|
|
99
|
+
console.log(' Auth profile already exists');
|
|
100
|
+
}
|
|
101
|
+
"
|
|
102
|
+
|
|
103
|
+
# 6. Add plugin to allow list (required for OpenClaw to load it)
|
|
104
|
+
echo "→ Adding to plugins allow list..."
|
|
105
|
+
node -e "
|
|
106
|
+
const os = require('os');
|
|
107
|
+
const fs = require('fs');
|
|
108
|
+
const path = require('path');
|
|
109
|
+
const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
|
|
110
|
+
|
|
111
|
+
if (fs.existsSync(configPath)) {
|
|
112
|
+
try {
|
|
113
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
114
|
+
|
|
115
|
+
// Ensure plugins.allow exists and includes clawrouter
|
|
116
|
+
if (!config.plugins) config.plugins = {};
|
|
117
|
+
if (!Array.isArray(config.plugins.allow)) {
|
|
118
|
+
config.plugins.allow = [];
|
|
119
|
+
}
|
|
120
|
+
if (!config.plugins.allow.includes('clawrouter') && !config.plugins.allow.includes('@blockrun/clawrouter')) {
|
|
121
|
+
config.plugins.allow.push('clawrouter');
|
|
122
|
+
console.log(' Added clawrouter to plugins.allow');
|
|
123
|
+
} else {
|
|
124
|
+
console.log(' Plugin already in allow list');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
128
|
+
} catch (e) {
|
|
129
|
+
console.log(' Could not update config:', e.message);
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
console.log(' No openclaw.json found, skipping');
|
|
133
|
+
}
|
|
134
|
+
"
|
|
135
|
+
|
|
136
|
+
# 7. Ensure apiKey is present for /model picker (but DON'T override default model)
|
|
137
|
+
echo "→ Finalizing setup..."
|
|
138
|
+
node -e "
|
|
139
|
+
const os = require('os');
|
|
140
|
+
const fs = require('fs');
|
|
141
|
+
const path = require('path');
|
|
142
|
+
const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
|
|
143
|
+
|
|
144
|
+
if (fs.existsSync(configPath)) {
|
|
145
|
+
try {
|
|
146
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
147
|
+
let changed = false;
|
|
148
|
+
|
|
149
|
+
// Ensure blockrun provider has apiKey (required by ModelRegistry for /model picker)
|
|
150
|
+
if (config.models?.providers?.blockrun && !config.models.providers.blockrun.apiKey) {
|
|
151
|
+
config.models.providers.blockrun.apiKey = 'x402-proxy-handles-auth';
|
|
152
|
+
console.log(' Added apiKey to blockrun provider config');
|
|
153
|
+
changed = true;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (changed) {
|
|
157
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
158
|
+
}
|
|
159
|
+
} catch (e) {
|
|
160
|
+
console.log(' Could not update config:', e.message);
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
console.log(' No openclaw.json found, skipping');
|
|
164
|
+
}
|
|
165
|
+
"
|
|
166
|
+
|
|
167
|
+
echo ""
|
|
168
|
+
echo "✓ Done! Smart routing enabled by default."
|
|
169
|
+
echo ""
|
|
170
|
+
echo "Run: openclaw gateway restart"
|
|
171
|
+
echo ""
|
|
172
|
+
echo "Model aliases available:"
|
|
173
|
+
echo " /model sonnet → anthropic/claude-sonnet-4"
|
|
174
|
+
echo " /model deepseek → deepseek/deepseek-chat"
|
|
175
|
+
echo " /model free → gpt-oss-120b (FREE)"
|
|
176
|
+
echo ""
|
|
177
|
+
echo "To uninstall: bash ~/.openclaw/extensions/clawrouter/scripts/uninstall.sh"
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
echo "🦞 ClawRouter Uninstall"
|
|
5
|
+
echo ""
|
|
6
|
+
|
|
7
|
+
# 1. Stop proxy
|
|
8
|
+
echo "→ Stopping proxy..."
|
|
9
|
+
lsof -ti :8402 | xargs kill -9 2>/dev/null || true
|
|
10
|
+
|
|
11
|
+
# 2. Remove plugin files
|
|
12
|
+
echo "→ Removing plugin files..."
|
|
13
|
+
rm -rf ~/.openclaw/extensions/clawrouter
|
|
14
|
+
|
|
15
|
+
# 3. Clean openclaw.json
|
|
16
|
+
echo "→ Cleaning openclaw.json..."
|
|
17
|
+
node -e "
|
|
18
|
+
const os = require('os');
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
|
|
22
|
+
|
|
23
|
+
if (!fs.existsSync(configPath)) {
|
|
24
|
+
console.log(' No openclaw.json found, skipping');
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
30
|
+
let changed = false;
|
|
31
|
+
|
|
32
|
+
// Remove blockrun provider
|
|
33
|
+
if (config.models?.providers?.blockrun) {
|
|
34
|
+
delete config.models.providers.blockrun;
|
|
35
|
+
console.log(' Removed blockrun provider');
|
|
36
|
+
changed = true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Remove plugin entries
|
|
40
|
+
if (config.plugins?.entries?.clawrouter) {
|
|
41
|
+
delete config.plugins.entries.clawrouter;
|
|
42
|
+
changed = true;
|
|
43
|
+
}
|
|
44
|
+
if (config.plugins?.installs?.clawrouter) {
|
|
45
|
+
delete config.plugins.installs.clawrouter;
|
|
46
|
+
changed = true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Remove from plugins.allow
|
|
50
|
+
if (Array.isArray(config.plugins?.allow)) {
|
|
51
|
+
const before = config.plugins.allow.length;
|
|
52
|
+
config.plugins.allow = config.plugins.allow.filter(
|
|
53
|
+
p => p !== 'clawrouter' && p !== '@blockrun/clawrouter'
|
|
54
|
+
);
|
|
55
|
+
if (config.plugins.allow.length !== before) {
|
|
56
|
+
console.log(' Removed from plugins.allow');
|
|
57
|
+
changed = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Reset default model if it's blockrun/auto
|
|
62
|
+
if (config.agents?.defaults?.model?.primary === 'blockrun/auto') {
|
|
63
|
+
delete config.agents.defaults.model.primary;
|
|
64
|
+
console.log(' Reset default model (was blockrun/auto)');
|
|
65
|
+
changed = true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Remove blockrun models from allowlist
|
|
69
|
+
if (config.agents?.defaults?.models) {
|
|
70
|
+
const models = config.agents.defaults.models;
|
|
71
|
+
let removedCount = 0;
|
|
72
|
+
for (const key of Object.keys(models)) {
|
|
73
|
+
if (key.startsWith('blockrun/')) {
|
|
74
|
+
delete models[key];
|
|
75
|
+
removedCount++;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (removedCount > 0) {
|
|
79
|
+
console.log(' Removed ' + removedCount + ' blockrun models from allowlist');
|
|
80
|
+
changed = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (changed) {
|
|
85
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
86
|
+
console.log(' Config cleaned');
|
|
87
|
+
} else {
|
|
88
|
+
console.log(' No changes needed');
|
|
89
|
+
}
|
|
90
|
+
} catch (err) {
|
|
91
|
+
console.error(' Error:', err.message);
|
|
92
|
+
}
|
|
93
|
+
"
|
|
94
|
+
|
|
95
|
+
# 4. Clean auth-profiles.json
|
|
96
|
+
echo "→ Cleaning auth profiles..."
|
|
97
|
+
node -e "
|
|
98
|
+
const os = require('os');
|
|
99
|
+
const fs = require('fs');
|
|
100
|
+
const path = require('path');
|
|
101
|
+
const agentsDir = path.join(os.homedir(), '.openclaw', 'agents');
|
|
102
|
+
|
|
103
|
+
if (!fs.existsSync(agentsDir)) {
|
|
104
|
+
console.log(' No agents directory found');
|
|
105
|
+
process.exit(0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const agents = fs.readdirSync(agentsDir, { withFileTypes: true })
|
|
109
|
+
.filter(d => d.isDirectory())
|
|
110
|
+
.map(d => d.name);
|
|
111
|
+
|
|
112
|
+
for (const agentId of agents) {
|
|
113
|
+
const authPath = path.join(agentsDir, agentId, 'agent', 'auth-profiles.json');
|
|
114
|
+
if (!fs.existsSync(authPath)) continue;
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const store = JSON.parse(fs.readFileSync(authPath, 'utf8'));
|
|
118
|
+
if (store.profiles?.['blockrun:default']) {
|
|
119
|
+
delete store.profiles['blockrun:default'];
|
|
120
|
+
fs.writeFileSync(authPath, JSON.stringify(store, null, 2));
|
|
121
|
+
console.log(' Removed blockrun auth from ' + agentId);
|
|
122
|
+
}
|
|
123
|
+
} catch {}
|
|
124
|
+
}
|
|
125
|
+
"
|
|
126
|
+
|
|
127
|
+
# 5. Clean models cache
|
|
128
|
+
echo "→ Cleaning models cache..."
|
|
129
|
+
rm -f ~/.openclaw/agents/*/agent/models.json 2>/dev/null || true
|
|
130
|
+
|
|
131
|
+
echo ""
|
|
132
|
+
echo "✓ ClawRouter uninstalled"
|
|
133
|
+
echo ""
|
|
134
|
+
echo "Restart OpenClaw to apply changes:"
|
|
135
|
+
echo " openclaw gateway restart"
|