@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 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
- // Generate a stable gateway ID
487
+ // 生成稳定的网关 ID
448
488
  generateGatewayId() {
449
489
  const host = os.hostname().split('.')[0].replace(/[^a-z0-9]/gi, '').toLowerCase();
450
- const suffix = Math.random().toString(36).substring(2, 8);
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
- const entries = Array.from(this.seenMessages);
1665
- for (let i = 0; i < entries.length / 2; i++) {
1666
- this.seenMessages.delete(entries[i]);
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
- this.metrics.set(`${data.name}_${Date.now()}`, data);
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
- const entries = Array.from(this.metrics.entries());
2015
- entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
2016
- for (let i = 0; i < 1e3; i++) {
2017
- this.metrics.delete(entries[i][0]);
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 count = (this.errorCounts.get(key) || 0) + 1;
2303
- this.errorCounts.set(key, count);
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: Date.now()
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
- const suffix = Math.random().toString(36).substring(2, 8);
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 { hostname as hostname2 } from "os";
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 createHash2, timingSafeEqual as timingSafeEqual2 } from "crypto";
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 createHash2("sha256").update(data + secret).digest("base64");
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
- const randomSuffix = Math.random().toString(36).substring(2, 8);
3317
- return `gw_openclaw_${hostname3}_${randomSuffix}`;
3391
+ return `gw_openclaw_${hostname3}_${MACHINE_ID2}`;
3318
3392
  }
3319
3393
  /**
3320
3394
  * 获取运行时主机名