@lingyao037/openclaw-lingyao-cli 0.5.3 → 0.6.0
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/cli.mjs +42 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.js +99 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -31,6 +31,46 @@ const RED = '\x1b[31m';
|
|
|
31
31
|
const CYAN = '\x1b[36m';
|
|
32
32
|
const NC = '\x1b[0m';
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* 获取机器的稳定标识符 (基于 MAC 地址)
|
|
36
|
+
*/
|
|
37
|
+
function getMachineId() {
|
|
38
|
+
try {
|
|
39
|
+
const interfaces = os.networkInterfaces();
|
|
40
|
+
let macStr = '';
|
|
41
|
+
|
|
42
|
+
for (const name of Object.keys(interfaces)) {
|
|
43
|
+
const iface = interfaces[name];
|
|
44
|
+
if (!iface) continue;
|
|
45
|
+
|
|
46
|
+
for (const alias of iface) {
|
|
47
|
+
if (!alias.internal && alias.mac && alias.mac !== '00:00:00:00:00:00') {
|
|
48
|
+
macStr += alias.mac;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (macStr) {
|
|
54
|
+
import('crypto').then(crypto => {
|
|
55
|
+
// this is async, but we want sync, so we just use require if possible
|
|
56
|
+
});
|
|
57
|
+
// fallback to simple hash since we can't use top level await here easily in older nodes
|
|
58
|
+
let hash = 0;
|
|
59
|
+
for (let i = 0; i < macStr.length; i++) {
|
|
60
|
+
const char = macStr.charCodeAt(i);
|
|
61
|
+
hash = ((hash << 5) - hash) + char;
|
|
62
|
+
hash = hash & hash;
|
|
63
|
+
}
|
|
64
|
+
return Math.abs(hash).toString(36).substring(0, 8);
|
|
65
|
+
}
|
|
66
|
+
} catch (e) {
|
|
67
|
+
// ignore
|
|
68
|
+
}
|
|
69
|
+
return Math.random().toString(36).substring(2, 10);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const MACHINE_ID = getMachineId();
|
|
73
|
+
|
|
34
74
|
class LingyaoInstaller {
|
|
35
75
|
constructor(customPath = null, skipDeps = true) {
|
|
36
76
|
this.openclawPath = null;
|
|
@@ -444,11 +484,10 @@ class LingyaoInstaller {
|
|
|
444
484
|
});
|
|
445
485
|
}
|
|
446
486
|
|
|
447
|
-
//
|
|
487
|
+
// 生成稳定的网关 ID
|
|
448
488
|
generateGatewayId() {
|
|
449
489
|
const host = os.hostname().split('.')[0].replace(/[^a-z0-9]/gi, '').toLowerCase();
|
|
450
|
-
|
|
451
|
-
return `gw_openclaw_${host}_default_${suffix}`;
|
|
490
|
+
return `gw_openclaw_${host}_${MACHINE_ID}_default`;
|
|
452
491
|
}
|
|
453
492
|
|
|
454
493
|
// Pair device flow: register gateway, init pairing, show QR, poll status
|
package/dist/index.d.ts
CHANGED
|
@@ -39,7 +39,11 @@ declare class ErrorHandler {
|
|
|
39
39
|
private errorCounts;
|
|
40
40
|
private lastErrors;
|
|
41
41
|
private errorThresholds;
|
|
42
|
+
private cleanupTimer;
|
|
43
|
+
private errorTimestamps;
|
|
42
44
|
constructor(runtime: LingyaoRuntime);
|
|
45
|
+
destroy(): void;
|
|
46
|
+
private cleanupOldErrors;
|
|
43
47
|
/**
|
|
44
48
|
* 处理错误
|
|
45
49
|
*/
|
package/dist/index.js
CHANGED
|
@@ -344,7 +344,8 @@ function createSetupAdapter() {
|
|
|
344
344
|
}
|
|
345
345
|
|
|
346
346
|
// src/orchestrator.ts
|
|
347
|
-
import { hostname } from "os";
|
|
347
|
+
import { hostname, networkInterfaces } from "os";
|
|
348
|
+
import { createHash as createHash2 } from "crypto";
|
|
348
349
|
|
|
349
350
|
// src/types.ts
|
|
350
351
|
var LINGYAO_SERVER_URL = "https://api.lingyao.live";
|
|
@@ -1661,9 +1662,12 @@ var MessageProcessor = class {
|
|
|
1661
1662
|
markMessageSeen(messageId) {
|
|
1662
1663
|
this.seenMessages.add(messageId);
|
|
1663
1664
|
if (this.seenMessages.size > 1e4) {
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1665
|
+
let count = 0;
|
|
1666
|
+
const targetDeletes = Math.floor(this.seenMessages.size / 2);
|
|
1667
|
+
for (const id of this.seenMessages) {
|
|
1668
|
+
this.seenMessages.delete(id);
|
|
1669
|
+
count++;
|
|
1670
|
+
if (count >= targetDeletes) break;
|
|
1667
1671
|
}
|
|
1668
1672
|
}
|
|
1669
1673
|
}
|
|
@@ -2009,12 +2013,14 @@ var MetricsManager = class {
|
|
|
2009
2013
|
* 记录指标
|
|
2010
2014
|
*/
|
|
2011
2015
|
recordMetric(data) {
|
|
2012
|
-
|
|
2016
|
+
const key = `${data.name}_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
2017
|
+
this.metrics.set(key, data);
|
|
2013
2018
|
if (this.metrics.size > 1e4) {
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
for (
|
|
2017
|
-
this.metrics.delete(
|
|
2019
|
+
let count = 0;
|
|
2020
|
+
const deleteCount = Math.floor(this.metrics.size * 0.1);
|
|
2021
|
+
for (const k of this.metrics.keys()) {
|
|
2022
|
+
this.metrics.delete(k);
|
|
2023
|
+
if (++count >= deleteCount) break;
|
|
2018
2024
|
}
|
|
2019
2025
|
}
|
|
2020
2026
|
}
|
|
@@ -2268,12 +2274,39 @@ var ErrorHandler = class {
|
|
|
2268
2274
|
errorCounts = /* @__PURE__ */ new Map();
|
|
2269
2275
|
lastErrors = /* @__PURE__ */ new Map();
|
|
2270
2276
|
errorThresholds = /* @__PURE__ */ new Map();
|
|
2277
|
+
cleanupTimer = null;
|
|
2278
|
+
errorTimestamps = /* @__PURE__ */ new Map();
|
|
2271
2279
|
constructor(runtime) {
|
|
2272
2280
|
this.runtime = runtime;
|
|
2281
|
+
this.cleanupTimer = setInterval(() => this.cleanupOldErrors(), 5 * 60 * 1e3);
|
|
2282
|
+
if (this.cleanupTimer.unref) {
|
|
2283
|
+
this.cleanupTimer.unref();
|
|
2284
|
+
}
|
|
2273
2285
|
this.setErrorThreshold("CONNECTION_ERROR", { count: 5, window: 6e4 });
|
|
2274
2286
|
this.setErrorThreshold("AUTHENTICATION_ERROR", { count: 3, window: 6e4 });
|
|
2275
2287
|
this.setErrorThreshold("NETWORK_ERROR", { count: 10, window: 6e4 });
|
|
2276
2288
|
}
|
|
2289
|
+
destroy() {
|
|
2290
|
+
if (this.cleanupTimer) {
|
|
2291
|
+
clearInterval(this.cleanupTimer);
|
|
2292
|
+
this.cleanupTimer = null;
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
cleanupOldErrors() {
|
|
2296
|
+
const now = Date.now();
|
|
2297
|
+
for (const [code, timestamps] of this.errorTimestamps.entries()) {
|
|
2298
|
+
const thresholdConfig = this.errorThresholds.get(code);
|
|
2299
|
+
const windowMs = thresholdConfig?.window || 36e5;
|
|
2300
|
+
const validTimestamps = timestamps.filter((ts) => now - ts <= windowMs);
|
|
2301
|
+
if (validTimestamps.length === 0) {
|
|
2302
|
+
this.errorTimestamps.delete(code);
|
|
2303
|
+
this.errorCounts.delete(code);
|
|
2304
|
+
} else {
|
|
2305
|
+
this.errorTimestamps.set(code, validTimestamps);
|
|
2306
|
+
this.errorCounts.set(code, validTimestamps.length);
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2277
2310
|
/**
|
|
2278
2311
|
* 处理错误
|
|
2279
2312
|
*/
|
|
@@ -2299,18 +2332,18 @@ var ErrorHandler = class {
|
|
|
2299
2332
|
*/
|
|
2300
2333
|
recordError(error) {
|
|
2301
2334
|
const key = error.code;
|
|
2302
|
-
const
|
|
2303
|
-
this.
|
|
2335
|
+
const timestamp = Date.now();
|
|
2336
|
+
const thresholdConfig = this.errorThresholds.get(key);
|
|
2337
|
+
const windowMs = thresholdConfig?.window || 36e5;
|
|
2338
|
+
let timestamps = this.errorTimestamps.get(key) || [];
|
|
2339
|
+
timestamps = timestamps.filter((ts) => timestamp - ts <= windowMs);
|
|
2340
|
+
timestamps.push(timestamp);
|
|
2341
|
+
this.errorTimestamps.set(key, timestamps);
|
|
2342
|
+
this.errorCounts.set(key, timestamps.length);
|
|
2304
2343
|
this.lastErrors.set(key, {
|
|
2305
2344
|
error,
|
|
2306
|
-
timestamp
|
|
2345
|
+
timestamp
|
|
2307
2346
|
});
|
|
2308
|
-
setTimeout(() => {
|
|
2309
|
-
const lastError = this.lastErrors.get(key);
|
|
2310
|
-
if (lastError && lastError.timestamp === error.timestamp) {
|
|
2311
|
-
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) - 1);
|
|
2312
|
-
}
|
|
2313
|
-
}, 36e5);
|
|
2314
2347
|
}
|
|
2315
2348
|
/**
|
|
2316
2349
|
* 检查错误阈值
|
|
@@ -2484,10 +2517,30 @@ var ErrorHandler = class {
|
|
|
2484
2517
|
};
|
|
2485
2518
|
|
|
2486
2519
|
// src/orchestrator.ts
|
|
2520
|
+
function getMachineId() {
|
|
2521
|
+
try {
|
|
2522
|
+
const interfaces = networkInterfaces();
|
|
2523
|
+
let macStr = "";
|
|
2524
|
+
for (const name of Object.keys(interfaces)) {
|
|
2525
|
+
const iface = interfaces[name];
|
|
2526
|
+
if (!iface) continue;
|
|
2527
|
+
for (const alias of iface) {
|
|
2528
|
+
if (!alias.internal && alias.mac && alias.mac !== "00:00:00:00:00:00") {
|
|
2529
|
+
macStr += alias.mac;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
if (macStr) {
|
|
2534
|
+
return createHash2("md5").update(macStr).digest("hex").substring(0, 8);
|
|
2535
|
+
}
|
|
2536
|
+
} catch (e) {
|
|
2537
|
+
}
|
|
2538
|
+
return Math.random().toString(36).substring(2, 10);
|
|
2539
|
+
}
|
|
2540
|
+
var MACHINE_ID = getMachineId();
|
|
2487
2541
|
function generateGatewayId(accountId) {
|
|
2488
2542
|
const host = hostname().split(".")[0].replace(/[^a-z0-9]/gi, "").toLowerCase();
|
|
2489
|
-
|
|
2490
|
-
return `gw_openclaw_${host}_${accountId}_${suffix}`;
|
|
2543
|
+
return `gw_openclaw_${host}_${MACHINE_ID}_${accountId}`;
|
|
2491
2544
|
}
|
|
2492
2545
|
var MultiAccountOrchestrator = class {
|
|
2493
2546
|
runtime;
|
|
@@ -2802,10 +2855,11 @@ var MultiAccountOrchestrator = class {
|
|
|
2802
2855
|
};
|
|
2803
2856
|
|
|
2804
2857
|
// src/channel.ts
|
|
2805
|
-
import {
|
|
2858
|
+
import { createHash as createHash4 } from "crypto";
|
|
2859
|
+
import { hostname as hostname2, networkInterfaces as networkInterfaces2 } from "os";
|
|
2806
2860
|
|
|
2807
2861
|
// src/token.ts
|
|
2808
|
-
import { randomBytes as randomBytes2, createHash as
|
|
2862
|
+
import { randomBytes as randomBytes2, createHash as createHash3, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
2809
2863
|
var TokenManager = class {
|
|
2810
2864
|
constructor(_runtime) {
|
|
2811
2865
|
void _runtime;
|
|
@@ -2921,7 +2975,7 @@ var TokenManager = class {
|
|
|
2921
2975
|
* Sign data with secret
|
|
2922
2976
|
*/
|
|
2923
2977
|
sign(data, secret) {
|
|
2924
|
-
return
|
|
2978
|
+
return createHash3("sha256").update(data + secret).digest("base64");
|
|
2925
2979
|
}
|
|
2926
2980
|
/**
|
|
2927
2981
|
* Base64URL encode without padding
|
|
@@ -2932,6 +2986,27 @@ var TokenManager = class {
|
|
|
2932
2986
|
};
|
|
2933
2987
|
|
|
2934
2988
|
// src/channel.ts
|
|
2989
|
+
function getMachineId2() {
|
|
2990
|
+
try {
|
|
2991
|
+
const interfaces = networkInterfaces2();
|
|
2992
|
+
let macStr = "";
|
|
2993
|
+
for (const name of Object.keys(interfaces)) {
|
|
2994
|
+
const iface = interfaces[name];
|
|
2995
|
+
if (!iface) continue;
|
|
2996
|
+
for (const alias of iface) {
|
|
2997
|
+
if (!alias.internal && alias.mac && alias.mac !== "00:00:00:00:00:00") {
|
|
2998
|
+
macStr += alias.mac;
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
if (macStr) {
|
|
3003
|
+
return createHash4("md5").update(macStr).digest("hex").substring(0, 8);
|
|
3004
|
+
}
|
|
3005
|
+
} catch (e) {
|
|
3006
|
+
}
|
|
3007
|
+
return Math.random().toString(36).substring(2, 10);
|
|
3008
|
+
}
|
|
3009
|
+
var MACHINE_ID2 = getMachineId2();
|
|
2935
3010
|
var LingyaoChannel = class {
|
|
2936
3011
|
runtime;
|
|
2937
3012
|
config;
|
|
@@ -3313,8 +3388,7 @@ var LingyaoChannel = class {
|
|
|
3313
3388
|
*/
|
|
3314
3389
|
generateGatewayId() {
|
|
3315
3390
|
const hostname3 = this.getRuntimeHostname();
|
|
3316
|
-
|
|
3317
|
-
return `gw_openclaw_${hostname3}_${randomSuffix}`;
|
|
3391
|
+
return `gw_openclaw_${hostname3}_${MACHINE_ID2}`;
|
|
3318
3392
|
}
|
|
3319
3393
|
/**
|
|
3320
3394
|
* 获取运行时主机名
|