@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/clawrouter",
3
- "version": "0.5.9",
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"