robot-resources 1.2.4 → 1.2.6
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/lib/detect.js +8 -0
- package/lib/tool-config.js +30 -132
- package/package.json +1 -1
package/lib/detect.js
CHANGED
|
@@ -80,6 +80,14 @@ export function isOpenClawInstalled() {
|
|
|
80
80
|
return existsSync(join(home, '.openclaw')) || existsSync(join(home, 'openclaw.json'));
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Check if the Robot Resources OpenClaw plugin is already installed.
|
|
85
|
+
*/
|
|
86
|
+
export function isOpenClawPluginInstalled() {
|
|
87
|
+
const home = homedir();
|
|
88
|
+
return existsSync(join(home, '.openclaw', 'extensions', 'robot-resources-router'));
|
|
89
|
+
}
|
|
90
|
+
|
|
83
91
|
/**
|
|
84
92
|
* Check if the router service is already registered.
|
|
85
93
|
*/
|
package/lib/tool-config.js
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { homedir } from 'node:os';
|
|
5
|
-
import { isOpenClawInstalled } from './detect.js';
|
|
6
|
-
|
|
7
|
-
const ROUTER_URL = 'http://localhost:3838';
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { isOpenClawInstalled, isOpenClawPluginInstalled } from './detect.js';
|
|
8
3
|
|
|
9
4
|
/**
|
|
10
5
|
* Strip JSON5 features (comments + trailing commas) to produce valid JSON.
|
|
@@ -24,135 +19,42 @@ function stripJson5(text) {
|
|
|
24
19
|
}
|
|
25
20
|
|
|
26
21
|
/**
|
|
27
|
-
*
|
|
28
|
-
* Strips comments and trailing commas before parsing.
|
|
29
|
-
*/
|
|
30
|
-
function readJsonSafe(filePath) {
|
|
31
|
-
try {
|
|
32
|
-
const raw = readFileSync(filePath, 'utf-8');
|
|
33
|
-
return JSON.parse(stripJson5(raw));
|
|
34
|
-
} catch {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Write JSON with backup.
|
|
41
|
-
*/
|
|
42
|
-
function writeJsonSafe(filePath, data) {
|
|
43
|
-
const dir = join(filePath, '..');
|
|
44
|
-
mkdirSync(dir, { recursive: true });
|
|
45
|
-
if (existsSync(filePath)) {
|
|
46
|
-
copyFileSync(filePath, `${filePath}.bak`);
|
|
47
|
-
}
|
|
48
|
-
writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Configure OpenClaw to route through the Router.
|
|
53
|
-
*
|
|
54
|
-
* Writes to TWO files (both required for OpenClaw to honor the override):
|
|
22
|
+
* Configure OpenClaw to route through Robot Resources Router.
|
|
55
23
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* that OpenClaw actually reads. The baseUrl here is what gets used for
|
|
61
|
-
* API calls. openclaw.json alone is not enough.
|
|
62
|
-
*
|
|
63
|
-
* Restarts the gateway via systemctl (SIGUSR1 doesn't reload config).
|
|
64
|
-
* The restart kills the current agent session, but it reconnects
|
|
65
|
-
* automatically within seconds.
|
|
24
|
+
* Installs the @robot-resources/openclaw-plugin via OpenClaw's
|
|
25
|
+
* native plugin system. The plugin uses before_model_resolve to
|
|
26
|
+
* override the provider — survives gateway restarts because it
|
|
27
|
+
* lives in ~/.openclaw/extensions/, not in openclaw.json.
|
|
66
28
|
*/
|
|
67
29
|
function configureOpenClaw() {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
join(home, 'openclaw.json'),
|
|
74
|
-
];
|
|
75
|
-
const configPath = configPaths.find((p) => existsSync(p)) || configPaths[0];
|
|
76
|
-
let config = readJsonSafe(configPath) || {};
|
|
77
|
-
|
|
78
|
-
// Ensure models.providers.anthropic path
|
|
79
|
-
config.models = config.models || {};
|
|
80
|
-
config.models.providers = config.models.providers || {};
|
|
81
|
-
config.models.providers.anthropic = config.models.providers.anthropic || {};
|
|
82
|
-
|
|
83
|
-
const anthropic = config.models.providers.anthropic;
|
|
84
|
-
|
|
85
|
-
// Check if already proxied through Router
|
|
86
|
-
if (anthropic.baseUrl === `${ROUTER_URL}/v1`) {
|
|
87
|
-
// Also verify models.json is in sync
|
|
88
|
-
const modelsJsonPath = join(home, '.openclaw', 'agents', 'main', 'agent', 'models.json');
|
|
89
|
-
const modelsJson = readJsonSafe(modelsJsonPath);
|
|
90
|
-
const runtimeUrl = modelsJson?.providers?.anthropic?.baseUrl;
|
|
91
|
-
if (runtimeUrl === `${ROUTER_URL}/v1`) {
|
|
92
|
-
return { name: 'OpenClaw', action: 'already_configured' };
|
|
93
|
-
}
|
|
94
|
-
// openclaw.json is set but models.json is not — fall through to fix it
|
|
30
|
+
if (isOpenClawPluginInstalled()) {
|
|
31
|
+
return {
|
|
32
|
+
name: 'OpenClaw',
|
|
33
|
+
action: 'already_configured',
|
|
34
|
+
};
|
|
95
35
|
}
|
|
96
36
|
|
|
97
|
-
// Save original baseUrl for rollback
|
|
98
|
-
if (anthropic.baseUrl && anthropic.baseUrl !== `${ROUTER_URL}/v1`) {
|
|
99
|
-
anthropic._originalBaseUrl = anthropic.baseUrl;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Point Anthropic provider at Router
|
|
103
|
-
anthropic.baseUrl = `${ROUTER_URL}/v1`;
|
|
104
|
-
|
|
105
|
-
// OpenClaw requires models array on provider entries
|
|
106
|
-
if (!Array.isArray(anthropic.models)) {
|
|
107
|
-
anthropic.models = [];
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Clean up stale "robot-resources" provider from previous wizard versions
|
|
111
|
-
delete config.models.providers['robot-resources'];
|
|
112
|
-
|
|
113
|
-
writeJsonSafe(configPath, config);
|
|
114
|
-
|
|
115
|
-
// ── 2. Update models.json (runtime file) ────────────────────
|
|
116
|
-
const modelsJsonPath = join(home, '.openclaw', 'agents', 'main', 'agent', 'models.json');
|
|
117
|
-
let modelsJson = readJsonSafe(modelsJsonPath) || {};
|
|
118
|
-
|
|
119
|
-
modelsJson.providers = modelsJson.providers || {};
|
|
120
|
-
modelsJson.providers.anthropic = modelsJson.providers.anthropic || {};
|
|
121
|
-
|
|
122
|
-
// Save original for rollback
|
|
123
|
-
const runtimeUrl = modelsJson.providers.anthropic.baseUrl;
|
|
124
|
-
if (runtimeUrl && runtimeUrl !== `${ROUTER_URL}/v1`) {
|
|
125
|
-
modelsJson.providers.anthropic._originalBaseUrl = runtimeUrl;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
modelsJson.providers.anthropic.baseUrl = `${ROUTER_URL}/v1`;
|
|
129
|
-
|
|
130
|
-
// Clean up stale robot-resources provider
|
|
131
|
-
delete modelsJson.providers['robot-resources'];
|
|
132
|
-
|
|
133
|
-
writeJsonSafe(modelsJsonPath, modelsJson);
|
|
134
|
-
|
|
135
|
-
// ── 3. Restart gateway ──────────────────────────────────────
|
|
136
|
-
// SIGUSR1 doesn't reload config on OpenClaw. Full restart needed.
|
|
137
|
-
// systemctl --user restart is preferred (auto-reconnects).
|
|
138
|
-
// Falls back to openclaw gateway restart, then kill+start.
|
|
139
37
|
try {
|
|
140
|
-
|
|
38
|
+
execFileSync('openclaw', ['plugins', 'install', '@robot-resources/openclaw-plugin'], {
|
|
141
39
|
stdio: 'ignore',
|
|
142
|
-
timeout:
|
|
40
|
+
timeout: 30_000,
|
|
143
41
|
});
|
|
42
|
+
return {
|
|
43
|
+
name: 'OpenClaw',
|
|
44
|
+
action: 'installed',
|
|
45
|
+
};
|
|
144
46
|
} catch {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
47
|
+
// Plugin install failed — fall back to instructions
|
|
48
|
+
return {
|
|
49
|
+
name: 'OpenClaw',
|
|
50
|
+
action: 'instructions',
|
|
51
|
+
instructions: [
|
|
52
|
+
'Could not auto-install plugin. Install manually:',
|
|
53
|
+
' openclaw plugins install @robot-resources/openclaw-plugin',
|
|
54
|
+
'Docs: https://github.com/robot-resources/robot-resources',
|
|
55
|
+
],
|
|
56
|
+
};
|
|
153
57
|
}
|
|
154
|
-
|
|
155
|
-
return { name: 'OpenClaw', action: 'configured' };
|
|
156
58
|
}
|
|
157
59
|
|
|
158
60
|
/**
|
|
@@ -165,15 +67,11 @@ export function configureToolRouting() {
|
|
|
165
67
|
|
|
166
68
|
// OpenClaw
|
|
167
69
|
if (isOpenClawInstalled()) {
|
|
168
|
-
|
|
169
|
-
results.push(configureOpenClaw());
|
|
170
|
-
} catch (err) {
|
|
171
|
-
results.push({ name: 'OpenClaw', action: 'error', reason: err.message });
|
|
172
|
-
}
|
|
70
|
+
results.push(configureOpenClaw());
|
|
173
71
|
}
|
|
174
72
|
|
|
175
73
|
return results;
|
|
176
74
|
}
|
|
177
75
|
|
|
178
76
|
// Exported for testing
|
|
179
|
-
export { stripJson5,
|
|
77
|
+
export { stripJson5, configureOpenClaw };
|