robot-resources 1.5.0 → 1.5.2
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/tool-config.js +40 -8
- package/lib/wizard.js +15 -5
- package/package.json +1 -1
package/lib/tool-config.js
CHANGED
|
@@ -1,10 +1,42 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
2
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { isOpenClawInstalled, isOpenClawPluginInstalled, getOpenClawAuthMode } from './detect.js';
|
|
6
6
|
import { stripJson5 } from './json5.js';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Run a command with a heartbeat to keep agent sessions alive.
|
|
10
|
+
* OC kills processes after 5s of no output (noOutputTimeoutMs).
|
|
11
|
+
* Prints immediately, then every 4s (safely under the 5s threshold).
|
|
12
|
+
*/
|
|
13
|
+
function spawnWithHeartbeat(cmd, args, { label, timeout = 30_000 } = {}) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
const proc = spawn(cmd, args, {
|
|
16
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
17
|
+
timeout,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
process.stdout.write(` ${label}...\n`);
|
|
21
|
+
let seconds = 0;
|
|
22
|
+
const heartbeat = setInterval(() => {
|
|
23
|
+
seconds += 4;
|
|
24
|
+
process.stdout.write(` ${label}... ${seconds}s\n`);
|
|
25
|
+
}, 4000);
|
|
26
|
+
|
|
27
|
+
proc.on('close', (code) => {
|
|
28
|
+
clearInterval(heartbeat);
|
|
29
|
+
if (code === 0) resolve();
|
|
30
|
+
else reject(new Error(`${cmd} ${args.join(' ')} exited with code ${code}`));
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
proc.on('error', (err) => {
|
|
34
|
+
clearInterval(heartbeat);
|
|
35
|
+
reject(err);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
8
40
|
/**
|
|
9
41
|
* Set robot-resources/auto as the default model in openclaw.json.
|
|
10
42
|
*
|
|
@@ -93,7 +125,7 @@ function registerScraperMcp() {
|
|
|
93
125
|
* OAuth tokens from third-party clients, so HTTP proxy won't work.
|
|
94
126
|
* - apikey: Plugin is preferred (survives restarts) but proxy also works.
|
|
95
127
|
*/
|
|
96
|
-
function configureOpenClaw() {
|
|
128
|
+
async function configureOpenClaw() {
|
|
97
129
|
const authMode = getOpenClawAuthMode();
|
|
98
130
|
|
|
99
131
|
if (isOpenClawPluginInstalled()) {
|
|
@@ -105,8 +137,8 @@ function configureOpenClaw() {
|
|
|
105
137
|
}
|
|
106
138
|
|
|
107
139
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
140
|
+
await spawnWithHeartbeat('openclaw', ['plugins', 'install', '@robot-resources/openclaw-plugin'], {
|
|
141
|
+
label: 'Installing plugin',
|
|
110
142
|
timeout: 30_000,
|
|
111
143
|
});
|
|
112
144
|
|
|
@@ -117,8 +149,8 @@ function configureOpenClaw() {
|
|
|
117
149
|
// Restart the gateway so it picks up the new plugin + config.
|
|
118
150
|
let gatewayRestarted = false;
|
|
119
151
|
try {
|
|
120
|
-
|
|
121
|
-
|
|
152
|
+
await spawnWithHeartbeat('openclaw', ['gateway', 'restart'], {
|
|
153
|
+
label: 'Restarting gateway',
|
|
122
154
|
timeout: 15_000,
|
|
123
155
|
});
|
|
124
156
|
gatewayRestarted = true;
|
|
@@ -167,12 +199,12 @@ function configureOpenClaw() {
|
|
|
167
199
|
*
|
|
168
200
|
* Returns array of { name, action, ... } results.
|
|
169
201
|
*/
|
|
170
|
-
export function configureToolRouting() {
|
|
202
|
+
export async function configureToolRouting() {
|
|
171
203
|
const results = [];
|
|
172
204
|
|
|
173
205
|
// OpenClaw
|
|
174
206
|
if (isOpenClawInstalled()) {
|
|
175
|
-
results.push(configureOpenClaw());
|
|
207
|
+
results.push(await configureOpenClaw());
|
|
176
208
|
}
|
|
177
209
|
|
|
178
210
|
return results;
|
package/lib/wizard.js
CHANGED
|
@@ -172,7 +172,7 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
172
172
|
blank();
|
|
173
173
|
step('Configuring AI tools to use Router...');
|
|
174
174
|
|
|
175
|
-
const toolResults = configureToolRouting();
|
|
175
|
+
const toolResults = await configureToolRouting();
|
|
176
176
|
results.tools = toolResults;
|
|
177
177
|
|
|
178
178
|
if (toolResults.length === 0) {
|
|
@@ -237,10 +237,20 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
237
237
|
// Restart gateway so OC picks up the scraper MCP server
|
|
238
238
|
if (scraperRegistered) {
|
|
239
239
|
try {
|
|
240
|
-
const {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
240
|
+
const { spawn: spawnProc } = await import('node:child_process');
|
|
241
|
+
await new Promise((resolve, reject) => {
|
|
242
|
+
const proc = spawnProc('openclaw', ['gateway', 'restart'], {
|
|
243
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
244
|
+
timeout: 15_000,
|
|
245
|
+
});
|
|
246
|
+
process.stdout.write(' Restarting gateway...\n');
|
|
247
|
+
let seconds = 0;
|
|
248
|
+
const hb = setInterval(() => {
|
|
249
|
+
seconds += 4;
|
|
250
|
+
process.stdout.write(` Restarting gateway... ${seconds}s\n`);
|
|
251
|
+
}, 4000);
|
|
252
|
+
proc.on('close', (code) => { clearInterval(hb); code === 0 ? resolve() : reject(new Error(`exit ${code}`)); });
|
|
253
|
+
proc.on('error', (err) => { clearInterval(hb); reject(err); });
|
|
244
254
|
});
|
|
245
255
|
success('OpenClaw gateway restarted');
|
|
246
256
|
results.scraper = true;
|