@lingyao037/openclaw-lingyao-cli 1.3.6 → 1.5.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/dist/index.js CHANGED
@@ -11,7 +11,7 @@ var globalRuntime = null;
11
11
  function setRuntime(runtime) {
12
12
  globalRuntime = runtime;
13
13
  }
14
- function adaptPluginRuntime(pr) {
14
+ function adaptPluginRuntime(pr, lingyaoConfig) {
15
15
  const noop = (..._args) => {
16
16
  };
17
17
  const rawLogger = pr.logging?.getChildLogger?.() ?? {
@@ -28,7 +28,10 @@ function adaptPluginRuntime(pr) {
28
28
  const stateDir = pr.state?.resolveStateDir?.() ?? join(process.cwd(), ".lingyao-data");
29
29
  const storeDir = join(stateDir, "lingyao");
30
30
  return {
31
- config: { enabled: true },
31
+ config: {
32
+ enabled: true,
33
+ ...lingyaoConfig
34
+ },
32
35
  logger: childLogger,
33
36
  storage: {
34
37
  async get(key) {
@@ -63,6 +66,113 @@ function adaptPluginRuntime(pr) {
63
66
  };
64
67
  }
65
68
 
69
+ // src/config-schema.ts
70
+ import { z } from "zod";
71
+ var lingyaoDmPolicySchema = z.enum(["pairing", "allowlist", "open"]);
72
+ var allowFromSchema = z.array(z.string()).optional();
73
+ var lingyaoAccountConfigSchema = z.object({
74
+ enabled: z.boolean().optional(),
75
+ dmPolicy: lingyaoDmPolicySchema.optional(),
76
+ allowFrom: allowFromSchema,
77
+ websocketHeartbeatIntervalMs: z.number().int().min(5e3).max(12e4).optional()
78
+ });
79
+ var lingyaoAccountConfigLooseSchema = z.object({
80
+ enabled: z.boolean().optional(),
81
+ dmPolicy: z.unknown().optional(),
82
+ allowFrom: z.array(z.string()).optional(),
83
+ gatewayId: z.string().optional(),
84
+ websocketHeartbeatIntervalMs: z.number().optional(),
85
+ maxOfflineMessages: z.number().optional(),
86
+ tokenExpiryDays: z.number().optional()
87
+ }).passthrough();
88
+ var lingyaoConfigSchema = z.object({
89
+ enabled: z.boolean().default(true),
90
+ dmPolicy: lingyaoDmPolicySchema.optional().default("pairing"),
91
+ allowFrom: allowFromSchema.default([]),
92
+ websocketHeartbeatIntervalMs: z.number().int().min(5e3).max(12e4).optional(),
93
+ notificationRatePerSecond: z.number().positive().max(500).optional(),
94
+ notificationBurst: z.number().int().positive().max(1e4).optional(),
95
+ defaultAccount: z.string().min(1).optional(),
96
+ accounts: z.record(lingyaoAccountConfigSchema).optional()
97
+ });
98
+ var lingyaoChannelConfigSchema = {
99
+ schema: {
100
+ type: "object",
101
+ additionalProperties: false,
102
+ properties: {
103
+ enabled: {
104
+ type: "boolean",
105
+ default: true
106
+ },
107
+ dmPolicy: {
108
+ type: "string",
109
+ enum: ["pairing", "allowlist", "open"],
110
+ default: "pairing"
111
+ },
112
+ allowFrom: {
113
+ type: "array",
114
+ items: { type: "string" },
115
+ default: []
116
+ },
117
+ defaultAccount: {
118
+ type: "string"
119
+ },
120
+ websocketHeartbeatIntervalMs: {
121
+ type: "integer",
122
+ minimum: 5e3,
123
+ maximum: 12e4,
124
+ description: "WebSocket gateway_heartbeat interval in ms (default: server register response). Use 5000\u201355000 for typical relay timeout."
125
+ },
126
+ notificationRatePerSecond: {
127
+ type: "number",
128
+ minimum: 0.1,
129
+ maximum: 500,
130
+ description: "Token bucket refill rate for outbound App notifications (default 15). Override with LINGYAO_NOTIFY_RATE_PER_SEC env if runtime config is not merged."
131
+ },
132
+ notificationBurst: {
133
+ type: "integer",
134
+ minimum: 1,
135
+ maximum: 1e4,
136
+ description: "Max burst for outbound notifications (default 25). Env: LINGYAO_NOTIFY_BURST."
137
+ },
138
+ accounts: {
139
+ type: "object",
140
+ additionalProperties: false,
141
+ properties: {
142
+ enabled: {
143
+ type: "boolean",
144
+ default: true
145
+ },
146
+ dmPolicy: {
147
+ type: "string",
148
+ enum: ["pairing", "allowlist", "open"]
149
+ },
150
+ allowFrom: {
151
+ type: "array",
152
+ items: { type: "string" }
153
+ },
154
+ websocketHeartbeatIntervalMs: {
155
+ type: "integer",
156
+ minimum: 5e3,
157
+ maximum: 12e4
158
+ }
159
+ },
160
+ default: {}
161
+ }
162
+ }
163
+ }
164
+ };
165
+ function validateConfig(config) {
166
+ return lingyaoConfigSchema.parse(config);
167
+ }
168
+ function getDefaultConfig() {
169
+ return {
170
+ enabled: true,
171
+ dmPolicy: "pairing",
172
+ allowFrom: []
173
+ };
174
+ }
175
+
66
176
  // src/adapters/config.ts
67
177
  function normalizeDmPolicy(raw) {
68
178
  switch (raw) {
@@ -128,13 +238,15 @@ function createConfigAdapter() {
128
238
  if (!accountConfig) {
129
239
  throw new Error(`Account "${resolvedId}" not found`);
130
240
  }
241
+ const parsed = lingyaoAccountConfigLooseSchema.safeParse(accountConfig);
242
+ const ac = parsed.success ? parsed.data : {};
131
243
  return {
132
244
  id: resolvedId,
133
245
  accountId: resolvedId,
134
- enabled: accountConfig?.enabled !== false,
135
- dmPolicy: normalizeDmPolicy(accountConfig?.dmPolicy),
136
- allowFrom: accountConfig?.allowFrom ?? [],
137
- gatewayId: accountConfig?.gatewayId,
246
+ enabled: ac.enabled !== false,
247
+ dmPolicy: normalizeDmPolicy(ac.dmPolicy),
248
+ allowFrom: Array.isArray(ac.allowFrom) ? ac.allowFrom : [],
249
+ gatewayId: typeof ac.gatewayId === "string" ? ac.gatewayId : void 0,
138
250
  rawConfig: accountConfig
139
251
  };
140
252
  },
@@ -764,6 +876,8 @@ var ServerHttpClient = class {
764
876
 
765
877
  // src/websocket-client.ts
766
878
  import WebSocket from "ws";
879
+ var LINGYAO_DEFAULT_MAX_MESSAGE_BYTES = 1048576;
880
+ var LINGYAO_DEFAULT_MAX_INCOMING_WS_BYTES = 2048576;
767
881
  function isWebsocketUpgradeNotFoundError(message) {
768
882
  return /Unexpected server response:\s*404/i.test(message) || /\b404\b/.test(message);
769
883
  }
@@ -790,6 +904,8 @@ var LingyaoWSClient = class {
790
904
  reconnectTimer = null;
791
905
  /** When set, close handler will not schedule reconnect (e.g. HTTP 404 on upgrade). */
792
906
  suppressReconnect = false;
907
+ /** 自上次成功 `open` 以来已调度的重连次数(用于退避与上限) */
908
+ reconnectAttempt = 0;
793
909
  messageHandlers = /* @__PURE__ */ new Map();
794
910
  logger;
795
911
  constructor(runtime, config) {
@@ -853,6 +969,7 @@ var LingyaoWSClient = class {
853
969
  */
854
970
  handleOpen() {
855
971
  this.state = "connected";
972
+ this.reconnectAttempt = 0;
856
973
  this.connectionId = this.generateConnectionId();
857
974
  this.logger.info("WebSocket connected to Lingyao server", {
858
975
  connectionId: this.connectionId
@@ -873,6 +990,14 @@ var LingyaoWSClient = class {
873
990
  */
874
991
  async handleMessage(data) {
875
992
  try {
993
+ const maxBytes = this.config.maxIncomingMessageBytes ?? LINGYAO_DEFAULT_MAX_INCOMING_WS_BYTES;
994
+ if (data.length > maxBytes) {
995
+ this.logger.warn("Dropped oversize WebSocket frame", {
996
+ bytes: data.length,
997
+ maxBytes
998
+ });
999
+ return;
1000
+ }
876
1001
  const message = JSON.parse(data.toString());
877
1002
  const rawType = String(message.type);
878
1003
  const handlerKey = normalizeIncomingGatewayMessageType(rawType);
@@ -941,8 +1066,7 @@ var LingyaoWSClient = class {
941
1066
  capabilities: {
942
1067
  websocket: true,
943
1068
  compression: false,
944
- maxMessageSize: 1048576
945
- // 1MB
1069
+ maxMessageSize: LINGYAO_DEFAULT_MAX_MESSAGE_BYTES
946
1070
  }
947
1071
  }
948
1072
  };
@@ -1006,11 +1130,33 @@ var LingyaoWSClient = class {
1006
1130
  if (this.reconnectTimer) {
1007
1131
  return;
1008
1132
  }
1009
- this.logger.info(`Scheduling reconnect in ${this.config.reconnectInterval}ms`);
1133
+ const maxAttempts = this.config.reconnectMaxAttempts ?? 0;
1134
+ if (maxAttempts > 0 && this.reconnectAttempt >= maxAttempts) {
1135
+ this.logger.error("Reconnect aborted: max attempts reached", {
1136
+ attempts: this.reconnectAttempt,
1137
+ maxAttempts
1138
+ });
1139
+ this.emitEvent({
1140
+ type: "reconnect_aborted",
1141
+ reason: "max_attempts",
1142
+ attempts: this.reconnectAttempt
1143
+ });
1144
+ return;
1145
+ }
1146
+ const base = this.config.reconnectInterval;
1147
+ const mult = this.config.reconnectBackoffMultiplier ?? 2;
1148
+ const cap = this.config.reconnectMaxDelayMs ?? 6e4;
1149
+ const pow = Math.pow(mult, this.reconnectAttempt);
1150
+ const delay = Math.min(base * pow, cap);
1151
+ this.logger.info(`Scheduling reconnect`, {
1152
+ delayMs: delay,
1153
+ attempt: this.reconnectAttempt
1154
+ });
1155
+ this.reconnectAttempt += 1;
1010
1156
  this.reconnectTimer = setTimeout(() => {
1011
1157
  this.reconnectTimer = null;
1012
1158
  this.connect();
1013
- }, this.config.reconnectInterval);
1159
+ }, delay);
1014
1160
  }
1015
1161
  /**
1016
1162
  * 发送消息到服务器
@@ -1091,9 +1237,9 @@ var LingyaoWSClient = class {
1091
1237
  if (this.config.eventHandler) {
1092
1238
  this.config.eventHandler({
1093
1239
  type: "pairing_completed",
1094
- deviceId: payload?.deviceId,
1095
- deviceInfo: payload?.deviceInfo,
1096
- sessionId: payload?.sessionId
1240
+ deviceId: payload?.deviceId ?? "",
1241
+ deviceInfo: payload?.deviceInfo ?? { name: "", platform: "", version: "" },
1242
+ sessionId: payload?.sessionId ?? ""
1097
1243
  });
1098
1244
  }
1099
1245
  }
@@ -1183,10 +1329,13 @@ var LingyaoWSClient = class {
1183
1329
  // src/accounts.ts
1184
1330
  var STORAGE_KEY_ACCOUNTS = "lingyao:accounts";
1185
1331
  var STORAGE_KEY_PENDING_PAIRINGS = "lingyao:pending_pairings";
1186
- var AccountManager = class {
1332
+ var AccountManager = class _AccountManager {
1187
1333
  runtime;
1188
1334
  accounts = /* @__PURE__ */ new Map();
1189
1335
  pendingPairings = /* @__PURE__ */ new Map();
1336
+ /** Debounced flush for high-frequency updates (e.g. heartbeat lastSeen). */
1337
+ accountsSaveTimer = null;
1338
+ static ACCOUNTS_SAVE_DEBOUNCE_MS = 3e3;
1190
1339
  constructor(runtime) {
1191
1340
  this.runtime = runtime;
1192
1341
  }
@@ -1309,7 +1458,31 @@ var AccountManager = class {
1309
1458
  const account = this.accounts.get(deviceId);
1310
1459
  if (account) {
1311
1460
  account.lastSeenAt = Date.now();
1312
- await this.saveAccounts();
1461
+ this.scheduleDebouncedAccountsSave();
1462
+ }
1463
+ }
1464
+ /**
1465
+ * Persist any debounced account state immediately (e.g. before process/account shutdown).
1466
+ */
1467
+ async flushPendingAccountsSave() {
1468
+ if (this.accountsSaveTimer) {
1469
+ clearTimeout(this.accountsSaveTimer);
1470
+ this.accountsSaveTimer = null;
1471
+ }
1472
+ await this.persistAccounts();
1473
+ }
1474
+ scheduleDebouncedAccountsSave() {
1475
+ if (this.accountsSaveTimer) {
1476
+ return;
1477
+ }
1478
+ this.accountsSaveTimer = setTimeout(() => {
1479
+ this.accountsSaveTimer = null;
1480
+ void this.persistAccounts().catch(
1481
+ (e) => this.runtime.logger.error("Failed to save accounts (debounced)", e)
1482
+ );
1483
+ }, _AccountManager.ACCOUNTS_SAVE_DEBOUNCE_MS);
1484
+ if (this.accountsSaveTimer.unref) {
1485
+ this.accountsSaveTimer.unref();
1313
1486
  }
1314
1487
  }
1315
1488
  /**
@@ -1394,9 +1567,16 @@ var AccountManager = class {
1394
1567
  }
1395
1568
  }
1396
1569
  /**
1397
- * Save accounts to storage
1570
+ * Save accounts to storage (immediate; clears any pending debounced save).
1398
1571
  */
1399
1572
  async saveAccounts() {
1573
+ if (this.accountsSaveTimer) {
1574
+ clearTimeout(this.accountsSaveTimer);
1575
+ this.accountsSaveTimer = null;
1576
+ }
1577
+ await this.persistAccounts();
1578
+ }
1579
+ async persistAccounts() {
1400
1580
  const accounts = Array.from(this.accounts.values());
1401
1581
  await this.runtime.storage.set(STORAGE_KEY_ACCOUNTS, accounts);
1402
1582
  }
@@ -1602,6 +1782,7 @@ var Probe = class {
1602
1782
  };
1603
1783
 
1604
1784
  // src/metrics.ts
1785
+ var MAX_HISTOGRAM_SAMPLES_PER_NAME = 1e4;
1605
1786
  var MetricsManager = class {
1606
1787
  metrics = /* @__PURE__ */ new Map();
1607
1788
  counters = /* @__PURE__ */ new Map();
@@ -1720,6 +1901,9 @@ var MetricsManager = class {
1720
1901
  this.histograms.set(name, values);
1721
1902
  }
1722
1903
  values.push(value);
1904
+ if (values.length > MAX_HISTOGRAM_SAMPLES_PER_NAME) {
1905
+ values.splice(0, values.length - MAX_HISTOGRAM_SAMPLES_PER_NAME);
1906
+ }
1723
1907
  this.recordMetric({
1724
1908
  name,
1725
1909
  type: "histogram" /* HISTOGRAM */,
@@ -1940,6 +2124,7 @@ var Monitor = class {
1940
2124
  };
1941
2125
 
1942
2126
  // src/errors.ts
2127
+ var MAX_LAST_ERROR_ENTRIES = 128;
1943
2128
  var LingyaoError = class extends Error {
1944
2129
  code;
1945
2130
  severity;
@@ -2058,6 +2243,11 @@ var ErrorHandler = class {
2058
2243
  error,
2059
2244
  timestamp
2060
2245
  });
2246
+ while (this.lastErrors.size > MAX_LAST_ERROR_ENTRIES) {
2247
+ const oldest = this.lastErrors.keys().next().value;
2248
+ if (oldest === void 0) break;
2249
+ this.lastErrors.delete(oldest);
2250
+ }
2061
2251
  }
2062
2252
  /**
2063
2253
  * 检查错误阈值
@@ -2230,6 +2420,50 @@ var ErrorHandler = class {
2230
2420
  }
2231
2421
  };
2232
2422
 
2423
+ // src/notification-rate-limit.ts
2424
+ var NotificationRateLimiter = class {
2425
+ constructor(refillPerSecond, burst) {
2426
+ this.refillPerSecond = refillPerSecond;
2427
+ this.burst = burst;
2428
+ }
2429
+ buckets = /* @__PURE__ */ new Map();
2430
+ /**
2431
+ * Attempt to consume one send slot for `accountId`. Returns false if rate-limited.
2432
+ */
2433
+ tryConsume(accountId) {
2434
+ const now = Date.now();
2435
+ let b = this.buckets.get(accountId);
2436
+ if (!b) {
2437
+ b = { tokens: this.burst, lastUpdate: now };
2438
+ this.buckets.set(accountId, b);
2439
+ }
2440
+ const elapsedSec = (now - b.lastUpdate) / 1e3;
2441
+ if (elapsedSec > 0) {
2442
+ b.tokens = Math.min(this.burst, b.tokens + elapsedSec * this.refillPerSecond);
2443
+ b.lastUpdate = now;
2444
+ }
2445
+ if (b.tokens >= 1) {
2446
+ b.tokens -= 1;
2447
+ return true;
2448
+ }
2449
+ return false;
2450
+ }
2451
+ };
2452
+ var DEFAULT_NOTIFY_REFILL_PER_SEC = 15;
2453
+ var DEFAULT_NOTIFY_BURST = 25;
2454
+ function resolveNotificationLimiterParams(cfg) {
2455
+ const envRef = typeof process !== "undefined" ? process.env.LINGYAO_NOTIFY_RATE_PER_SEC : void 0;
2456
+ const envBurst = typeof process !== "undefined" ? process.env.LINGYAO_NOTIFY_BURST : void 0;
2457
+ const refillFromEnv = envRef !== void 0 && envRef !== "" ? Number(envRef) : Number.NaN;
2458
+ const burstFromEnv = envBurst !== void 0 && envBurst !== "" ? Number(envBurst) : Number.NaN;
2459
+ const refill = cfg.notificationRatePerSecond ?? (!Number.isNaN(refillFromEnv) && refillFromEnv > 0 ? refillFromEnv : void 0) ?? DEFAULT_NOTIFY_REFILL_PER_SEC;
2460
+ const burst = cfg.notificationBurst ?? (!Number.isNaN(burstFromEnv) && burstFromEnv > 0 ? Math.floor(burstFromEnv) : void 0) ?? DEFAULT_NOTIFY_BURST;
2461
+ return {
2462
+ refillPerSecond: Math.min(500, Math.max(0.1, refill)),
2463
+ burst: Math.min(1e4, Math.max(1, Math.floor(burst)))
2464
+ };
2465
+ }
2466
+
2233
2467
  // src/orchestrator.ts
2234
2468
  function getMachineId() {
2235
2469
  try {
@@ -2247,8 +2481,11 @@ function generateGatewayId(accountId) {
2247
2481
  var MultiAccountOrchestrator = class {
2248
2482
  runtime;
2249
2483
  accounts = /* @__PURE__ */ new Map();
2484
+ notificationLimiter;
2250
2485
  constructor(runtime) {
2251
2486
  this.runtime = runtime;
2487
+ const lim = resolveNotificationLimiterParams(runtime.config);
2488
+ this.notificationLimiter = new NotificationRateLimiter(lim.refillPerSecond, lim.burst);
2252
2489
  }
2253
2490
  /**
2254
2491
  * Start an account: create components, register to server, connect WS.
@@ -2351,6 +2588,11 @@ var MultiAccountOrchestrator = class {
2351
2588
  if (state.httpClient) {
2352
2589
  state.httpClient.stopHeartbeat();
2353
2590
  }
2591
+ try {
2592
+ await state.accountManager.flushPendingAccountsSave();
2593
+ } catch (e) {
2594
+ this.runtime.logger.error(`[${accountId}] Failed to flush account storage`, e);
2595
+ }
2354
2596
  state.status = "stopped";
2355
2597
  this.runtime.logger.info(`Account "${accountId}" stopped`);
2356
2598
  }
@@ -2407,6 +2649,12 @@ var MultiAccountOrchestrator = class {
2407
2649
  this.runtime.logger.warn(`[${accountId}] Cannot send notification: WS not connected`, { deviceId });
2408
2650
  return false;
2409
2651
  }
2652
+ if (!this.notificationLimiter.tryConsume(accountId)) {
2653
+ this.runtime.logger.warn(`[${accountId}] Notification rate limited (relay protection)`, {
2654
+ deviceId
2655
+ });
2656
+ return false;
2657
+ }
2410
2658
  this.runtime.logger.info(`[${accountId}] Sending notification to device`, {
2411
2659
  deviceId,
2412
2660
  notificationType: notification.type
@@ -2439,7 +2687,7 @@ var MultiAccountOrchestrator = class {
2439
2687
  const response = await state.httpClient.register({
2440
2688
  websocket: true,
2441
2689
  compression: false,
2442
- maxMessageSize: 1048576
2690
+ maxMessageSize: LINGYAO_DEFAULT_MAX_MESSAGE_BYTES
2443
2691
  });
2444
2692
  this.runtime.logger.info(`Account "${state.accountId}": registered successfully`, {
2445
2693
  expiresAt: new Date(response.expiresAt).toISOString()
@@ -2466,17 +2714,14 @@ var MultiAccountOrchestrator = class {
2466
2714
  deviceId,
2467
2715
  messageType: msg.type
2468
2716
  });
2469
- switch (msg.type) {
2470
- case "sync_diary":
2471
- case "sync_memory":
2472
- await this.handleSyncMessage(state, deviceId, msg);
2473
- break;
2474
- case "heartbeat":
2475
- await state.accountManager.updateLastSeen(deviceId);
2476
- state.monitor.recordEvent("heartbeat_received" /* HEARTBEAT_RECEIVED */, { deviceId });
2477
- break;
2478
- default:
2479
- this.runtime.logger.warn(`[${state.accountId}] Unknown message type`, { type: msg.type });
2717
+ if (msg.type === "sync_diary" || msg.type === "sync_memory") {
2718
+ const syncBody = msg;
2719
+ await this.handleSyncMessage(state, deviceId, syncBody);
2720
+ } else if (msg.type === "heartbeat") {
2721
+ await state.accountManager.updateLastSeen(deviceId);
2722
+ state.monitor.recordEvent("heartbeat_received" /* HEARTBEAT_RECEIVED */, { deviceId });
2723
+ } else {
2724
+ this.runtime.logger.warn(`[${state.accountId}] Unknown message type`, { type: msg.type });
2480
2725
  }
2481
2726
  } catch (error) {
2482
2727
  this.runtime.logger.error(`[${state.accountId}] Error handling App message`, error);
@@ -2609,12 +2854,20 @@ var MultiAccountOrchestrator = class {
2609
2854
  break;
2610
2855
  case "fatal_handshake":
2611
2856
  if (event.reason === "http_404") {
2612
- void this.handleWsHandshake404(state);
2857
+ this.handleWsHandshake404(state).catch((err) => {
2858
+ this.runtime.logger.error(`[${state.accountId}] WS 404 recovery (async) failed`, err);
2859
+ });
2613
2860
  }
2614
2861
  break;
2615
2862
  case "pairing_completed":
2616
2863
  this.handlePairingCompleted(state, event);
2617
2864
  break;
2865
+ case "reconnect_aborted":
2866
+ this.runtime.logger.error(`[${state.accountId}] WebSocket reconnect aborted`, {
2867
+ reason: event.reason,
2868
+ attempts: event.attempts
2869
+ });
2870
+ break;
2618
2871
  }
2619
2872
  };
2620
2873
  }
@@ -2657,7 +2910,7 @@ var MultiAccountOrchestrator = class {
2657
2910
  const response = await httpClient.register({
2658
2911
  websocket: true,
2659
2912
  compression: false,
2660
- maxMessageSize: 1048576
2913
+ maxMessageSize: LINGYAO_DEFAULT_MAX_MESSAGE_BYTES
2661
2914
  });
2662
2915
  wsClient.updateToken(response.gatewayToken);
2663
2916
  await wsClient.connect();
@@ -2686,7 +2939,7 @@ var MultiAccountOrchestrator = class {
2686
2939
  const response = await state.httpClient.register({
2687
2940
  websocket: true,
2688
2941
  compression: false,
2689
- maxMessageSize: 1048576
2942
+ maxMessageSize: LINGYAO_DEFAULT_MAX_MESSAGE_BYTES
2690
2943
  });
2691
2944
  this.runtime.logger.info(`[${state.accountId}] Obtained new token. Reconnecting WS...`);
2692
2945
  state.wsClient.updateToken(response.gatewayToken);
@@ -2698,90 +2951,6 @@ var MultiAccountOrchestrator = class {
2698
2951
  }
2699
2952
  };
2700
2953
 
2701
- // src/config-schema.ts
2702
- import { z } from "zod";
2703
- var lingyaoDmPolicySchema = z.enum(["pairing", "allowlist", "open"]);
2704
- var allowFromSchema = z.array(z.string()).optional();
2705
- var lingyaoAccountConfigSchema = z.object({
2706
- enabled: z.boolean().optional(),
2707
- dmPolicy: lingyaoDmPolicySchema.optional(),
2708
- allowFrom: allowFromSchema,
2709
- websocketHeartbeatIntervalMs: z.number().int().min(5e3).max(12e4).optional()
2710
- });
2711
- var lingyaoConfigSchema = z.object({
2712
- enabled: z.boolean().default(true),
2713
- dmPolicy: lingyaoDmPolicySchema.optional().default("pairing"),
2714
- allowFrom: allowFromSchema.default([]),
2715
- websocketHeartbeatIntervalMs: z.number().int().min(5e3).max(12e4).optional(),
2716
- defaultAccount: z.string().min(1).optional(),
2717
- accounts: z.record(lingyaoAccountConfigSchema).optional()
2718
- });
2719
- var lingyaoChannelConfigSchema = {
2720
- schema: {
2721
- type: "object",
2722
- additionalProperties: false,
2723
- properties: {
2724
- enabled: {
2725
- type: "boolean",
2726
- default: true
2727
- },
2728
- dmPolicy: {
2729
- type: "string",
2730
- enum: ["pairing", "allowlist", "open"],
2731
- default: "pairing"
2732
- },
2733
- allowFrom: {
2734
- type: "array",
2735
- items: { type: "string" },
2736
- default: []
2737
- },
2738
- defaultAccount: {
2739
- type: "string"
2740
- },
2741
- websocketHeartbeatIntervalMs: {
2742
- type: "integer",
2743
- minimum: 5e3,
2744
- maximum: 12e4,
2745
- description: "WebSocket gateway_heartbeat interval in ms (default: server register response). Use 5000\u201355000 for typical relay timeout."
2746
- },
2747
- accounts: {
2748
- type: "object",
2749
- additionalProperties: false,
2750
- properties: {
2751
- enabled: {
2752
- type: "boolean",
2753
- default: true
2754
- },
2755
- dmPolicy: {
2756
- type: "string",
2757
- enum: ["pairing", "allowlist", "open"]
2758
- },
2759
- allowFrom: {
2760
- type: "array",
2761
- items: { type: "string" }
2762
- },
2763
- websocketHeartbeatIntervalMs: {
2764
- type: "integer",
2765
- minimum: 5e3,
2766
- maximum: 12e4
2767
- }
2768
- },
2769
- default: {}
2770
- }
2771
- }
2772
- }
2773
- };
2774
- function validateConfig(config) {
2775
- return lingyaoConfigSchema.parse(config);
2776
- }
2777
- function getDefaultConfig() {
2778
- return {
2779
- enabled: true,
2780
- dmPolicy: "pairing",
2781
- allowFrom: []
2782
- };
2783
- }
2784
-
2785
2954
  // src/api.ts
2786
2955
  var orchestrator = null;
2787
2956
  function getOrchestrator() {
@@ -2865,15 +3034,18 @@ var lingyaoPlugin = {
2865
3034
  directory: directoryAdapter,
2866
3035
  messaging: messagingAdapter
2867
3036
  };
2868
- function initializeLingyaoRuntime(runtime) {
2869
- const adapted = adaptPluginRuntime(runtime);
3037
+ function initializeLingyaoRuntime(runtime, options) {
3038
+ const adapted = adaptPluginRuntime(
3039
+ runtime,
3040
+ options?.lingyaoConfig
3041
+ );
2870
3042
  setRuntime(adapted);
2871
3043
  orchestrator = new MultiAccountOrchestrator(adapted);
2872
3044
  }
2873
3045
 
2874
3046
  // src/runtime-api.ts
2875
- function setLingyaoRuntime(runtime) {
2876
- initializeLingyaoRuntime(runtime);
3047
+ function setLingyaoRuntime(runtime, options) {
3048
+ initializeLingyaoRuntime(runtime, options);
2877
3049
  }
2878
3050
 
2879
3051
  // src/index.ts