squad-openclaw 2026.2.2024 → 2026.2.2203
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/dist/index.js +150 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -215,6 +215,7 @@ var RelayClient = class {
|
|
|
215
215
|
localConnectAttempts = /* @__PURE__ */ new Map();
|
|
216
216
|
reconnectAttempts = 0;
|
|
217
217
|
maxReconnectAttempts = 100;
|
|
218
|
+
autoConnectCounter = 0;
|
|
218
219
|
reconnectTimer = null;
|
|
219
220
|
shouldReconnect = true;
|
|
220
221
|
destroyed = false;
|
|
@@ -482,6 +483,21 @@ var RelayClient = class {
|
|
|
482
483
|
}
|
|
483
484
|
if (!conn.connectHandshakeComplete) {
|
|
484
485
|
conn.pendingMessages.push(msg);
|
|
486
|
+
if (!conn.pendingConnect) {
|
|
487
|
+
const autoConnect = this.buildAutoConnectRequest();
|
|
488
|
+
conn.pendingConnect = autoConnect;
|
|
489
|
+
console.log(`[relay-client] Auto-starting local connect handshake for ${userId} (${String(autoConnect.id)})`);
|
|
490
|
+
if (conn.challengeNonce) {
|
|
491
|
+
const pending = conn.pendingConnect;
|
|
492
|
+
conn.pendingConnect = null;
|
|
493
|
+
if (pending) {
|
|
494
|
+
this.injectDeviceIdentity(conn, pending);
|
|
495
|
+
if (conn.localWs.readyState === NodeWebSocket.OPEN) {
|
|
496
|
+
conn.localWs.send(JSON.stringify(pending));
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
485
501
|
return;
|
|
486
502
|
}
|
|
487
503
|
if (conn.localWs.readyState === NodeWebSocket.CONNECTING) {
|
|
@@ -492,6 +508,26 @@ var RelayClient = class {
|
|
|
492
508
|
}
|
|
493
509
|
conn.localWs.send(JSON.stringify(msg));
|
|
494
510
|
}
|
|
511
|
+
buildAutoConnectRequest() {
|
|
512
|
+
return {
|
|
513
|
+
type: "req",
|
|
514
|
+
id: `connect-auto-${++this.autoConnectCounter}`,
|
|
515
|
+
method: "connect",
|
|
516
|
+
params: {
|
|
517
|
+
minProtocol: 3,
|
|
518
|
+
maxProtocol: 3,
|
|
519
|
+
client: {
|
|
520
|
+
id: "cli",
|
|
521
|
+
version: "relay-client-auto",
|
|
522
|
+
platform: "gateway",
|
|
523
|
+
mode: "ui"
|
|
524
|
+
},
|
|
525
|
+
role: "operator",
|
|
526
|
+
scopes: ["operator.admin", "operator.read", "operator.write"],
|
|
527
|
+
auth: {}
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
}
|
|
495
531
|
/**
|
|
496
532
|
* Inject auth token and device identity into a connect request.
|
|
497
533
|
*
|
|
@@ -2147,7 +2183,7 @@ function registerSqlTools(api) {
|
|
|
2147
2183
|
}
|
|
2148
2184
|
|
|
2149
2185
|
// src/version.ts
|
|
2150
|
-
import {
|
|
2186
|
+
import { spawn } from "child_process";
|
|
2151
2187
|
import fs9 from "fs";
|
|
2152
2188
|
import path10 from "path";
|
|
2153
2189
|
import { fileURLToPath } from "url";
|
|
@@ -2157,6 +2193,9 @@ var updateInProgress = false;
|
|
|
2157
2193
|
var VERIFY_TIMEOUT_MS = 2e4;
|
|
2158
2194
|
var VERIFY_INTERVAL_MS = 500;
|
|
2159
2195
|
var RESTART_BUFFER_MS = 5e3;
|
|
2196
|
+
var REGISTRY_TIMEOUT_MS = 2500;
|
|
2197
|
+
var COMMAND_OUTPUT_LIMIT = 8e3;
|
|
2198
|
+
var COMMAND_KILL_GRACE_MS = 2e3;
|
|
2160
2199
|
function readInstalledVersionFromConfig() {
|
|
2161
2200
|
try {
|
|
2162
2201
|
const raw = fs9.readFileSync(CONFIG_PATH, "utf-8");
|
|
@@ -2207,9 +2246,9 @@ function getCurrentVersion() {
|
|
|
2207
2246
|
return "0.0.0";
|
|
2208
2247
|
}
|
|
2209
2248
|
}
|
|
2210
|
-
async function fetchLatestVersion() {
|
|
2249
|
+
async function fetchLatestVersion(timeoutMs = REGISTRY_TIMEOUT_MS) {
|
|
2211
2250
|
const controller = new AbortController();
|
|
2212
|
-
const timeout = setTimeout(() => controller.abort(),
|
|
2251
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
2213
2252
|
try {
|
|
2214
2253
|
const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`, {
|
|
2215
2254
|
signal: controller.signal
|
|
@@ -2221,14 +2260,64 @@ async function fetchLatestVersion() {
|
|
|
2221
2260
|
clearTimeout(timeout);
|
|
2222
2261
|
}
|
|
2223
2262
|
}
|
|
2224
|
-
function
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2263
|
+
async function runCommand(args, timeoutMs) {
|
|
2264
|
+
return new Promise((resolve) => {
|
|
2265
|
+
const child = spawn("openclaw", args, {
|
|
2266
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2267
|
+
detached: true
|
|
2229
2268
|
});
|
|
2230
|
-
|
|
2231
|
-
|
|
2269
|
+
let output = "";
|
|
2270
|
+
let timedOut = false;
|
|
2271
|
+
let resolved = false;
|
|
2272
|
+
let killGraceTimer = null;
|
|
2273
|
+
const append = (chunk) => {
|
|
2274
|
+
output += chunk.toString();
|
|
2275
|
+
if (output.length > COMMAND_OUTPUT_LIMIT) {
|
|
2276
|
+
output = output.slice(output.length - COMMAND_OUTPUT_LIMIT);
|
|
2277
|
+
}
|
|
2278
|
+
};
|
|
2279
|
+
const finalize = (result) => {
|
|
2280
|
+
if (resolved) return;
|
|
2281
|
+
resolved = true;
|
|
2282
|
+
if (killGraceTimer) clearTimeout(killGraceTimer);
|
|
2283
|
+
clearTimeout(timeout);
|
|
2284
|
+
resolve(result);
|
|
2285
|
+
};
|
|
2286
|
+
child.stdout?.on("data", append);
|
|
2287
|
+
child.stderr?.on("data", append);
|
|
2288
|
+
child.on("error", (err2) => {
|
|
2289
|
+
append(String(err2));
|
|
2290
|
+
finalize({
|
|
2291
|
+
ok: false,
|
|
2292
|
+
timedOut,
|
|
2293
|
+
exitCode: null,
|
|
2294
|
+
signal: null,
|
|
2295
|
+
output
|
|
2296
|
+
});
|
|
2297
|
+
});
|
|
2298
|
+
child.on("close", (code, signal) => {
|
|
2299
|
+
finalize({
|
|
2300
|
+
ok: !timedOut && code === 0,
|
|
2301
|
+
timedOut,
|
|
2302
|
+
exitCode: code,
|
|
2303
|
+
signal,
|
|
2304
|
+
output
|
|
2305
|
+
});
|
|
2306
|
+
});
|
|
2307
|
+
const timeout = setTimeout(() => {
|
|
2308
|
+
timedOut = true;
|
|
2309
|
+
try {
|
|
2310
|
+
process.kill(-child.pid, "SIGTERM");
|
|
2311
|
+
} catch {
|
|
2312
|
+
}
|
|
2313
|
+
killGraceTimer = setTimeout(() => {
|
|
2314
|
+
try {
|
|
2315
|
+
process.kill(-child.pid, "SIGKILL");
|
|
2316
|
+
} catch {
|
|
2317
|
+
}
|
|
2318
|
+
}, COMMAND_KILL_GRACE_MS);
|
|
2319
|
+
}, timeoutMs);
|
|
2320
|
+
});
|
|
2232
2321
|
}
|
|
2233
2322
|
function sleep(ms) {
|
|
2234
2323
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -2363,13 +2452,25 @@ async function waitForVerifiedInstall() {
|
|
|
2363
2452
|
function registerVersionMethods(api) {
|
|
2364
2453
|
api.registerGatewayMethod(
|
|
2365
2454
|
"squad.version.check",
|
|
2366
|
-
async ({ respond }) => {
|
|
2455
|
+
async ({ respond, params }) => {
|
|
2367
2456
|
try {
|
|
2457
|
+
const checkParams = params ?? {};
|
|
2368
2458
|
const current = getCurrentVersion();
|
|
2459
|
+
if (checkParams.skipRegistry) {
|
|
2460
|
+
console.log("[version_check_local] returning local version only");
|
|
2461
|
+
respond(true, {
|
|
2462
|
+
current,
|
|
2463
|
+
latest: null,
|
|
2464
|
+
updateAvailable: false,
|
|
2465
|
+
registrySkipped: true
|
|
2466
|
+
});
|
|
2467
|
+
return;
|
|
2468
|
+
}
|
|
2369
2469
|
let latest;
|
|
2370
2470
|
try {
|
|
2371
2471
|
latest = await fetchLatestVersion();
|
|
2372
2472
|
} catch {
|
|
2473
|
+
console.log("[version_check_registry_timeout] npm registry unavailable");
|
|
2373
2474
|
respond(true, {
|
|
2374
2475
|
current,
|
|
2375
2476
|
latest: null,
|
|
@@ -2397,6 +2498,7 @@ function registerVersionMethods(api) {
|
|
|
2397
2498
|
return;
|
|
2398
2499
|
}
|
|
2399
2500
|
updateInProgress = true;
|
|
2501
|
+
const updateAttemptId = `${Date.now()}-${Math.random().toString(16).slice(2, 8)}`;
|
|
2400
2502
|
try {
|
|
2401
2503
|
const before = getCurrentVersion();
|
|
2402
2504
|
const beforeInstalledVersion = readInstalledVersionFromConfig();
|
|
@@ -2412,19 +2514,25 @@ function registerVersionMethods(api) {
|
|
|
2412
2514
|
configBackup = fs9.readFileSync(CONFIG_PATH, "utf-8");
|
|
2413
2515
|
} catch {
|
|
2414
2516
|
}
|
|
2415
|
-
|
|
2517
|
+
await runCommand(["doctor", "--fix"], 3e4);
|
|
2416
2518
|
try {
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2519
|
+
const first = await runCommand(["plugins", "update", PACKAGE_NAME], 12e4);
|
|
2520
|
+
updateOutput = first.output;
|
|
2521
|
+
if (!first.ok) {
|
|
2522
|
+
throw new Error(
|
|
2523
|
+
first.timedOut ? "UPDATE_TIMEOUT: plugins update timed out" : `UPDATE_FAILED: plugins update exited with code ${String(first.exitCode)}`
|
|
2524
|
+
);
|
|
2525
|
+
}
|
|
2421
2526
|
} catch (firstErr) {
|
|
2422
|
-
|
|
2527
|
+
await runCommand(["doctor", "--fix"], 3e4);
|
|
2423
2528
|
try {
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2529
|
+
const retry = await runCommand(["plugins", "update", PACKAGE_NAME], 12e4);
|
|
2530
|
+
updateOutput = retry.output;
|
|
2531
|
+
if (!retry.ok) {
|
|
2532
|
+
throw new Error(
|
|
2533
|
+
retry.timedOut ? "UPDATE_TIMEOUT: plugins update timed out after retry" : `UPDATE_FAILED: plugins update retry exited with code ${String(retry.exitCode)}`
|
|
2534
|
+
);
|
|
2535
|
+
}
|
|
2428
2536
|
} catch (installErr) {
|
|
2429
2537
|
if (configBackup) {
|
|
2430
2538
|
try {
|
|
@@ -2435,9 +2543,11 @@ function registerVersionMethods(api) {
|
|
|
2435
2543
|
const firstMsg = firstErr instanceof Error ? firstErr.message : String(firstErr);
|
|
2436
2544
|
const retryMsg = installErr instanceof Error ? installErr.message : String(installErr);
|
|
2437
2545
|
respond(false, {
|
|
2546
|
+
code: /UPDATE_TIMEOUT/.test(retryMsg) ? "UPDATE_TIMEOUT" : "UPDATE_FAILED",
|
|
2438
2547
|
error: `Update failed after doctor fix retry: ${retryMsg}`,
|
|
2439
2548
|
output: updateOutput,
|
|
2440
|
-
firstError: firstMsg
|
|
2549
|
+
firstError: firstMsg,
|
|
2550
|
+
updateAttemptId
|
|
2441
2551
|
});
|
|
2442
2552
|
return;
|
|
2443
2553
|
}
|
|
@@ -2451,9 +2561,11 @@ function registerVersionMethods(api) {
|
|
|
2451
2561
|
}
|
|
2452
2562
|
}
|
|
2453
2563
|
respond(false, {
|
|
2564
|
+
code: "VERIFY_FAILED",
|
|
2454
2565
|
error: `Update verification failed: ${verification.reason ?? "unknown error"}`,
|
|
2455
2566
|
output: updateOutput.slice(0, 500),
|
|
2456
|
-
verification
|
|
2567
|
+
verification,
|
|
2568
|
+
updateAttemptId
|
|
2457
2569
|
});
|
|
2458
2570
|
return;
|
|
2459
2571
|
}
|
|
@@ -2462,10 +2574,12 @@ function registerVersionMethods(api) {
|
|
|
2462
2574
|
if (beforeInstalledVersion && verificationAfterReconcile.packageVersion && beforeInstalledVersion === verificationAfterReconcile.packageVersion) {
|
|
2463
2575
|
const alreadyLatest = !!latestVersion && compareVersions(verificationAfterReconcile.packageVersion, latestVersion) >= 0;
|
|
2464
2576
|
respond(false, {
|
|
2577
|
+
code: "UPDATE_FAILED",
|
|
2465
2578
|
error: alreadyLatest ? `Already at latest version (${verificationAfterReconcile.packageVersion}).` : `Update command completed but installed version did not change (${verificationAfterReconcile.packageVersion}).`,
|
|
2466
2579
|
output: updateOutput.slice(0, 500),
|
|
2467
2580
|
verification: verificationAfterReconcile,
|
|
2468
|
-
latestVersion
|
|
2581
|
+
latestVersion,
|
|
2582
|
+
updateAttemptId
|
|
2469
2583
|
});
|
|
2470
2584
|
return;
|
|
2471
2585
|
}
|
|
@@ -2478,22 +2592,27 @@ function registerVersionMethods(api) {
|
|
|
2478
2592
|
restartInMs: RESTART_BUFFER_MS,
|
|
2479
2593
|
verification: verificationAfterReconcile,
|
|
2480
2594
|
latestVersion,
|
|
2481
|
-
output: updateOutput.slice(0, 500)
|
|
2595
|
+
output: updateOutput.slice(0, 500),
|
|
2596
|
+
updateAttemptId
|
|
2482
2597
|
});
|
|
2483
2598
|
await sleep(RESTART_BUFFER_MS);
|
|
2484
2599
|
console.log(
|
|
2485
2600
|
`[version] Plugin update verified (was ${before}), restarting gateway...`
|
|
2486
2601
|
);
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2602
|
+
const restartResult = await runCommand(["gateway", "restart"], 3e4);
|
|
2603
|
+
if (!restartResult.ok && !restartResult.timedOut) {
|
|
2604
|
+
console.log("[update_cmd_timeout] restart command failed unexpectedly", {
|
|
2605
|
+
updateAttemptId,
|
|
2606
|
+
exitCode: restartResult.exitCode,
|
|
2607
|
+
signal: restartResult.signal
|
|
2491
2608
|
});
|
|
2492
|
-
} catch {
|
|
2493
2609
|
}
|
|
2494
2610
|
} catch (e) {
|
|
2495
2611
|
const msg = e instanceof Error ? e.message : String(e);
|
|
2496
|
-
respond(false, {
|
|
2612
|
+
respond(false, {
|
|
2613
|
+
code: /VERIFY_FAILED/.test(msg) ? "VERIFY_FAILED" : /UPDATE_TIMEOUT/.test(msg) ? "UPDATE_TIMEOUT" : "UPDATE_FAILED",
|
|
2614
|
+
error: msg
|
|
2615
|
+
});
|
|
2497
2616
|
} finally {
|
|
2498
2617
|
updateInProgress = false;
|
|
2499
2618
|
}
|
package/package.json
CHANGED