@honor-claw/yoyo 1.2.1-beta.3 → 1.3.0-alpha.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.
Files changed (91) hide show
  1. package/dist/index.mjs +3814 -0
  2. package/package.json +13 -8
  3. package/skills/yoyo-control/SKILL.md +163 -394
  4. package/skills/yoyo-control/configs/sub-skills.json +54 -0
  5. package/index.ts +0 -32
  6. package/src/apis/claw-cloud.ts +0 -167
  7. package/src/apis/helpers.ts +0 -10
  8. package/src/apis/hosts.ts +0 -48
  9. package/src/apis/http-client.ts +0 -227
  10. package/src/apis/index.ts +0 -7
  11. package/src/apis/types.ts +0 -114
  12. package/src/cloud-channel/admin-client-manager.ts +0 -133
  13. package/src/cloud-channel/channel.ts +0 -116
  14. package/src/cloud-channel/client.ts +0 -364
  15. package/src/cloud-channel/index.ts +0 -4
  16. package/src/cloud-channel/message-handler.ts +0 -694
  17. package/src/cloud-channel/session-manager.ts +0 -137
  18. package/src/cloud-channel/types.ts +0 -144
  19. package/src/cloud-channel/utils.ts +0 -61
  20. package/src/commands/env/impl.ts +0 -72
  21. package/src/commands/env/index.ts +0 -1
  22. package/src/commands/index.ts +0 -24
  23. package/src/commands/login/impl.ts +0 -20
  24. package/src/commands/login/index.ts +0 -1
  25. package/src/commands/logout/impl.ts +0 -25
  26. package/src/commands/logout/index.ts +0 -1
  27. package/src/commands/status/index.ts +0 -176
  28. package/src/gateway-client/admin-client.ts +0 -80
  29. package/src/gateway-client/client.ts +0 -90
  30. package/src/gateway-client/index.ts +0 -5
  31. package/src/gateway-client/node-client.ts +0 -79
  32. package/src/gateway-client/protocol-client.ts +0 -325
  33. package/src/gateway-client/types/client.ts +0 -71
  34. package/src/gateway-client/types/index.ts +0 -4
  35. package/src/gateway-client/types/model.ts +0 -11
  36. package/src/gateway-client/types/protocol.ts +0 -197
  37. package/src/gateway-client/types/skills.ts +0 -53
  38. package/src/honor-auth/auth-result-html.ts +0 -241
  39. package/src/honor-auth/browser.ts +0 -86
  40. package/src/honor-auth/callback-server.ts +0 -190
  41. package/src/honor-auth/cloud.ts +0 -37
  42. package/src/honor-auth/config.ts +0 -40
  43. package/src/honor-auth/honor-auth-client.ts +0 -103
  44. package/src/honor-auth/index.ts +0 -5
  45. package/src/honor-auth/token-manager.ts +0 -143
  46. package/src/honor-auth/types.ts +0 -35
  47. package/src/index.ts +0 -10
  48. package/src/modules/configs/config-manager.ts +0 -530
  49. package/src/modules/configs/identity-persist.ts +0 -153
  50. package/src/modules/configs/index.ts +0 -8
  51. package/src/modules/configs/provider.ts +0 -361
  52. package/src/modules/configs/types.ts +0 -69
  53. package/src/modules/device/auth.ts +0 -27
  54. package/src/modules/device/credential-builder.ts +0 -58
  55. package/src/modules/device/device-info.ts +0 -81
  56. package/src/modules/device/helpers.ts +0 -26
  57. package/src/modules/device/identity.ts +0 -202
  58. package/src/modules/device/index.ts +0 -8
  59. package/src/modules/device/providers/base.ts +0 -32
  60. package/src/modules/device/providers/index.ts +0 -56
  61. package/src/modules/device/providers/linux.ts +0 -84
  62. package/src/modules/device/providers/macos.ts +0 -58
  63. package/src/modules/device/providers/pad.ts +0 -136
  64. package/src/modules/device/providers/windows.ts +0 -188
  65. package/src/modules/device/registry.ts +0 -27
  66. package/src/modules/device/types.ts +0 -53
  67. package/src/modules/login/impl.ts +0 -71
  68. package/src/modules/login/index.ts +0 -6
  69. package/src/modules/prompt/index.ts +0 -6
  70. package/src/runtime.ts +0 -45
  71. package/src/schemas.ts +0 -42
  72. package/src/services/connection/impl.ts +0 -234
  73. package/src/services/connection/index.ts +0 -1
  74. package/src/services/connection/status-tracker/events.ts +0 -172
  75. package/src/services/connection/status-tracker/index.ts +0 -31
  76. package/src/services/connection/status-tracker/storage.ts +0 -133
  77. package/src/services/connection/status-tracker/tracker.ts +0 -358
  78. package/src/services/connection/status-tracker/types.ts +0 -136
  79. package/src/services/connection/types.ts +0 -20
  80. package/src/types.ts +0 -69
  81. package/src/utils/env.ts +0 -64
  82. package/src/utils/error.ts +0 -13
  83. package/src/utils/fs-safe.ts +0 -543
  84. package/src/utils/home-dir.ts +0 -50
  85. package/src/utils/id.ts +0 -8
  86. package/src/utils/jwt.ts +0 -38
  87. package/src/utils/logger.ts +0 -20
  88. package/src/utils/proxy.ts +0 -58
  89. package/src/utils/version.ts +0 -29
  90. package/src/utils/ws.ts +0 -21
  91. package/src/vite-env.d.ts +0 -1
package/dist/index.mjs ADDED
@@ -0,0 +1,3814 @@
1
+ import e, { promises as t, readFileSync as n } from "fs";
2
+ import * as r from "path";
3
+ import { dirname as i, join as a } from "path";
4
+ import { fileURLToPath as o } from "url";
5
+ import s, { constants as c, existsSync as l } from "node:fs";
6
+ import u from "node:path";
7
+ import d from "open";
8
+ import { customAlphabet as f } from "nanoid";
9
+ import { ProxyAgent as p, request as m } from "undici";
10
+ import { HttpProxyAgent as ee } from "http-proxy-agent";
11
+ import { HttpsProxyAgent as te } from "https-proxy-agent";
12
+ import { createServer as ne } from "http";
13
+ import { URL as re, fileURLToPath as h } from "node:url";
14
+ import { createHash as g, randomBytes as ie } from "crypto";
15
+ import _, { createHash as ae, randomUUID as oe } from "node:crypto";
16
+ import v from "node:fs/promises";
17
+ import se from "node:os";
18
+ import y from "os";
19
+ import { execFile as ce } from "child_process";
20
+ import { promisify as le } from "util";
21
+ import * as b from "winreg";
22
+ import { z as x } from "zod";
23
+ import S, { WebSocket as ue } from "ws";
24
+ import { Buffer as C } from "node:buffer";
25
+ //#region src/utils/version.ts
26
+ var w = null;
27
+ function de() {
28
+ if (w !== null) return !!w;
29
+ try {
30
+ let e = n(a(i(o(import.meta.url)), "../../package.json"), "utf-8");
31
+ w = (JSON.parse(e).version || "").includes("beta");
32
+ } catch (e) {
33
+ console.error(`Failed to check version: ${e}`);
34
+ }
35
+ return !!w;
36
+ }
37
+ //#endregion
38
+ //#region src/runtime.ts
39
+ var fe = null;
40
+ function pe(e) {
41
+ fe = e;
42
+ }
43
+ function me() {
44
+ if (!fe) throw Error("Yoyo runtime not initialized");
45
+ return fe;
46
+ }
47
+ function he() {
48
+ try {
49
+ let e = j();
50
+ return {
51
+ env: e.getEnvInfo().env,
52
+ grayTag: e.getGrayTag()
53
+ };
54
+ } catch (e) {
55
+ return console.error(`[runtime] Failed to get env info from config: ${e}`), { env: "production" };
56
+ }
57
+ }
58
+ //#endregion
59
+ //#region src/utils/env.ts
60
+ var T = {
61
+ brand: "YOYO_CLAW_BRAND",
62
+ manufacture: "YOYO_CLAW_MANUFACTURER",
63
+ deviceType: "YOYO_CLAW_DEVICE_TYPE",
64
+ userId: "YOYO_CLAW_USER_ID"
65
+ }, ge = "YOYO_CLAW_ENV", _e = {
66
+ dev: "dev",
67
+ pre: "test",
68
+ test: "test",
69
+ prd: "production",
70
+ production: "production"
71
+ };
72
+ function ve() {
73
+ return {
74
+ brand: process.env[T.brand],
75
+ manufacture: process.env[T.manufacture],
76
+ deviceType: process.env[T.deviceType]
77
+ };
78
+ }
79
+ function ye() {
80
+ return process.env[T.userId];
81
+ }
82
+ function be() {
83
+ let e = process.env[ge];
84
+ if (e) return _e[e.toLowerCase()];
85
+ }
86
+ //#endregion
87
+ //#region src/utils/error.ts
88
+ function E(e, t) {
89
+ let n = e instanceof Error ? e.message : String(e);
90
+ return Error(`${t}: ${n}`, { cause: e });
91
+ }
92
+ //#endregion
93
+ //#region src/utils/logger.ts
94
+ var xe = null;
95
+ function Se(e) {
96
+ xe = e;
97
+ }
98
+ function D() {
99
+ return xe || {
100
+ debug: console.debug,
101
+ info: console.log,
102
+ warn: console.warn,
103
+ error: console.error
104
+ };
105
+ }
106
+ //#endregion
107
+ //#region src/modules/configs/provider.ts
108
+ function Ce(e) {
109
+ let t = {};
110
+ if (!e.models?.providers) return t;
111
+ let n = Object.keys(e.models.providers);
112
+ for (let e of n) {
113
+ let n = e.trim().toLowerCase();
114
+ n.includes("minimax") && (t[e] = n.replace("minimax", "mini_max"));
115
+ }
116
+ return t;
117
+ }
118
+ function we(e, t) {
119
+ let n = { ...e };
120
+ if (n.models?.providers) {
121
+ let e = {};
122
+ for (let [r, i] of Object.entries(n.models.providers)) {
123
+ let n = t[r];
124
+ n ? e[n] = i : e[r] = i;
125
+ }
126
+ n.models = {
127
+ ...n.models,
128
+ providers: e
129
+ };
130
+ }
131
+ return n.agents &&= Te(n.agents, t), n.auth?.profiles && (n.auth = {
132
+ ...n.auth,
133
+ profiles: Oe(n.auth.profiles, t)
134
+ }, je(t)), n;
135
+ }
136
+ function Te(e, t) {
137
+ let n = { ...e };
138
+ return n.defaults &&= Ee(n.defaults, t), n.list &&= n.list.map((e) => De(e, t)), n;
139
+ }
140
+ function Ee(e, t) {
141
+ let n = { ...e };
142
+ if (n.model &&= O(n.model, t), n.imageModel &&= O(n.imageModel, t), n.pdfModel &&= O(n.pdfModel, t), n.models) {
143
+ let e = {};
144
+ for (let [r, i] of Object.entries(n.models)) {
145
+ let n = k(r, t);
146
+ e[n] = i;
147
+ }
148
+ n.models = e;
149
+ }
150
+ return n.subagents?.model && (n.subagents = {
151
+ ...n.subagents,
152
+ model: O(n.subagents.model, t)
153
+ }), n;
154
+ }
155
+ function De(e, t) {
156
+ let n = { ...e };
157
+ return n.model &&= O(n.model, t), n.subagents?.model && (n.subagents = {
158
+ ...n.subagents,
159
+ model: O(n.subagents.model, t)
160
+ }), n;
161
+ }
162
+ function O(e, t) {
163
+ if (typeof e == "string") return k(e, t);
164
+ if (typeof e == "object" && e) {
165
+ let n = { ...e };
166
+ return n.primary &&= k(n.primary, t), n.fallbacks && Array.isArray(n.fallbacks) && (n.fallbacks = n.fallbacks.map((e) => k(e, t))), n;
167
+ }
168
+ return e;
169
+ }
170
+ function k(e, t) {
171
+ let n = e.split("/");
172
+ if (n.length > 0) {
173
+ let e = t[n[0]];
174
+ if (e) return n[0] = e, n.join("/");
175
+ }
176
+ return e;
177
+ }
178
+ function Oe(e, t) {
179
+ let n = {};
180
+ for (let [r, i] of Object.entries(e)) {
181
+ let e = { ...i }, a = t[e.provider];
182
+ a && (e.provider = a), n[r] = e;
183
+ }
184
+ return n;
185
+ }
186
+ function ke() {
187
+ return process.platform === "win32" ? process.env.USERPROFILE || "" : process.env.HOME || "";
188
+ }
189
+ function Ae(e) {
190
+ let t = [], n = ke(), r = e || u.join(n, ".openclaw"), i = u.join(r, "agents", "main", "agent", "auth-profiles.json");
191
+ s.existsSync(i) && t.push(i);
192
+ let a = u.join(r, "agents");
193
+ if (s.existsSync(a)) {
194
+ let e = s.readdirSync(a, { withFileTypes: !0 });
195
+ for (let n of e) if (n.isDirectory()) {
196
+ let e = u.join(a, n.name, "agent", "auth-profiles.json");
197
+ s.existsSync(e) && !t.includes(e) && t.push(e);
198
+ }
199
+ }
200
+ return t;
201
+ }
202
+ function je(e, t) {
203
+ let n = Ae(t), r = [], i = [], a = !1;
204
+ for (let t of n) try {
205
+ let n = s.readFileSync(t, "utf-8"), i = JSON.parse(n);
206
+ if (!i.profiles || typeof i.profiles != "object") continue;
207
+ let o = !1;
208
+ for (let [t, n] of Object.entries(i.profiles)) {
209
+ let t = n, r = t.provider, i = e[r];
210
+ i && r !== i && (t.provider = i, o = !0);
211
+ }
212
+ if (i.order && typeof i.order == "object") {
213
+ let t = {};
214
+ for (let [n, r] of Object.entries(i.order)) {
215
+ let i = e[n], a = i || n;
216
+ t[a] = r, i && n !== i && (o = !0);
217
+ }
218
+ o && (i.order = t);
219
+ }
220
+ if (i.lastGood && typeof i.lastGood == "object") {
221
+ let t = {};
222
+ for (let [n, r] of Object.entries(i.lastGood)) {
223
+ let i = e[n], a = i || n;
224
+ t[a] = r, i && n !== i && (o = !0);
225
+ }
226
+ o && (i.lastGood = t);
227
+ }
228
+ o && (s.writeFileSync(t, JSON.stringify(i, null, 2) + "\n", "utf-8"), r.push(t), a = !0);
229
+ } catch (e) {
230
+ let n = e instanceof Error ? e.message : String(e);
231
+ i.push(`${t}: ${n}`);
232
+ }
233
+ return {
234
+ updated: a,
235
+ files: r,
236
+ errors: i
237
+ };
238
+ }
239
+ //#endregion
240
+ //#region src/modules/configs/config-manager.ts
241
+ var A = "yoyo", Me = { watch: !0 }, Ne = 250, Pe = /* @__PURE__ */ "alarm.create,alarm.delete,alarm.disable,alarm.enable,alarm.query,alarm.update,app.close,app.open,call.phone,call.search,capture-screenshot,contact.search,file-upload,hotspot,local-search,message.search,message.send,mobile-data,no-disturb,quiet-mode,ringing-mode,schedule.create,schedule.delete,schedule.search,schedule.update,screen-record,vibration-mode,volume.operate,wlan,bluetooth,location-service,nfc,usb-shared-network,eyecomfort,status-bar-show,brightness,autoscreen-onnotice,dark-mode,device-operation,camera,app.uninstall,audio-record,battery,gui.create,gui.pause,gui.terminate,mcp.tool.call".split(","), Fe = class {
242
+ loadConfig() {
243
+ try {
244
+ return me().config.loadConfig();
245
+ } catch (e) {
246
+ throw E(e, "Failed to load config");
247
+ }
248
+ }
249
+ async saveConfig(e) {
250
+ try {
251
+ await me().config.writeConfigFile(e);
252
+ } catch (e) {
253
+ throw E(e, "Failed to save config");
254
+ }
255
+ }
256
+ getGatewayAuthConfig() {
257
+ try {
258
+ let e = this.loadConfig().gateway?.auth;
259
+ if (!e) return;
260
+ let t = {
261
+ token: "",
262
+ password: ""
263
+ };
264
+ return e.token && (t.token = e.token), e.password && (t.password = e.password), Object.keys(t).length === 0 ? void 0 : t;
265
+ } catch (e) {
266
+ console.error(`[claw-configs] Failed to read gateway auth config: ${e}`);
267
+ return;
268
+ }
269
+ }
270
+ getGatewayPort() {
271
+ try {
272
+ return this.loadConfig().gateway?.port ?? 18789;
273
+ } catch (e) {
274
+ return console.error(`[claw-configs] Failed to read gateway port config: ${e}`), 18789;
275
+ }
276
+ }
277
+ getUserConfig() {
278
+ try {
279
+ return this.loadConfig().plugins?.entries?.[A]?.config?.user;
280
+ } catch (e) {
281
+ console.error(`[claw-configs] Failed to read user config: ${e}`);
282
+ return;
283
+ }
284
+ }
285
+ getEnvInfo() {
286
+ try {
287
+ let e = this.loadConfig().plugins?.entries?.[A]?.config, t = e?.envInfo;
288
+ if (t?.env) return t;
289
+ let n = e?.env;
290
+ if (n) return {
291
+ env: n,
292
+ source: "manual"
293
+ };
294
+ let r = be();
295
+ return r ? {
296
+ env: r,
297
+ source: "env"
298
+ } : {
299
+ env: "production",
300
+ source: "env"
301
+ };
302
+ } catch (e) {
303
+ return console.error(`[claw-configs] Failed to read env config: ${e}`), {
304
+ env: "production",
305
+ source: "env"
306
+ };
307
+ }
308
+ }
309
+ getGrayTag() {
310
+ try {
311
+ return this.loadConfig().plugins?.entries?.[A]?.config?.gray;
312
+ } catch (e) {
313
+ console.error(`[claw-configs] Failed to read gray tag config: ${e}`);
314
+ return;
315
+ }
316
+ }
317
+ getDeviceConfig() {
318
+ try {
319
+ return this.loadConfig().plugins?.entries?.[A]?.config?.device;
320
+ } catch (e) {
321
+ console.error(`[claw-configs] Failed to read device config: ${e}`);
322
+ return;
323
+ }
324
+ }
325
+ async updateDeviceConfig(e) {
326
+ try {
327
+ let t = this.loadConfig(), n = t.plugins?.entries?.[A]?.config?.device || {}, r = {
328
+ ...t,
329
+ plugins: {
330
+ ...t.plugins,
331
+ entries: {
332
+ ...t.plugins?.entries,
333
+ [A]: {
334
+ ...t.plugins?.entries?.[A],
335
+ enabled: !0,
336
+ config: {
337
+ ...t.plugins?.entries?.[A]?.config,
338
+ device: {
339
+ ...n,
340
+ ...e
341
+ }
342
+ }
343
+ }
344
+ }
345
+ }
346
+ };
347
+ await this.saveConfig(r);
348
+ } catch (e) {
349
+ throw E(e, "Failed to update device config");
350
+ }
351
+ }
352
+ async updateEnv(e) {
353
+ try {
354
+ let t = this.loadConfig(), n = {
355
+ ...t,
356
+ plugins: {
357
+ ...t.plugins,
358
+ entries: {
359
+ ...t.plugins?.entries,
360
+ [A]: {
361
+ ...t.plugins?.entries?.[A],
362
+ enabled: !0,
363
+ config: {
364
+ ...t.plugins?.entries?.[A]?.config,
365
+ envInfo: {
366
+ env: e,
367
+ source: "manual"
368
+ },
369
+ env: void 0
370
+ }
371
+ }
372
+ }
373
+ }
374
+ };
375
+ await this.saveConfig(n);
376
+ } catch (e) {
377
+ throw E(e, "Failed to update env config");
378
+ }
379
+ }
380
+ async resetEnv() {
381
+ try {
382
+ let e = this.loadConfig(), t = e.plugins?.entries?.[A]?.config?.envInfo;
383
+ if (!t?.env) return;
384
+ let n = {
385
+ ...e,
386
+ plugins: {
387
+ ...e.plugins,
388
+ entries: {
389
+ ...e.plugins?.entries,
390
+ [A]: {
391
+ ...e.plugins?.entries?.[A],
392
+ enabled: !0,
393
+ config: {
394
+ ...e.plugins?.entries?.[A]?.config,
395
+ envInfo: {
396
+ env: t.env,
397
+ source: "env"
398
+ }
399
+ }
400
+ }
401
+ }
402
+ }
403
+ };
404
+ await this.saveConfig(n);
405
+ } catch (e) {
406
+ throw E(e, "Failed to reset env config");
407
+ }
408
+ }
409
+ async updateGrayTag(e) {
410
+ try {
411
+ let t = this.loadConfig(), n = {
412
+ ...t,
413
+ plugins: {
414
+ ...t.plugins,
415
+ entries: {
416
+ ...t.plugins?.entries,
417
+ [A]: {
418
+ ...t.plugins?.entries?.[A],
419
+ enabled: !0,
420
+ config: {
421
+ ...t.plugins?.entries?.[A]?.config,
422
+ ...e && { gray: e }
423
+ }
424
+ }
425
+ }
426
+ }
427
+ };
428
+ await this.saveConfig(n);
429
+ } catch (e) {
430
+ throw E(e, "Failed to update gray tag config");
431
+ }
432
+ }
433
+ async updateUserConfig(e) {
434
+ try {
435
+ let t = this.loadConfig(), n = {
436
+ ...t,
437
+ plugins: {
438
+ ...t.plugins,
439
+ entries: {
440
+ ...t.plugins?.entries,
441
+ [A]: {
442
+ ...t.plugins?.entries?.[A],
443
+ enabled: !0,
444
+ config: {
445
+ ...t.plugins?.entries?.[A]?.config,
446
+ user: e
447
+ }
448
+ }
449
+ }
450
+ }
451
+ };
452
+ await this.saveConfig(n);
453
+ } catch (e) {
454
+ throw E(e, "Failed to update user config");
455
+ }
456
+ }
457
+ async clearUserConfig() {
458
+ try {
459
+ let e = this.loadConfig(), t = {
460
+ ...e,
461
+ plugins: {
462
+ ...e.plugins,
463
+ entries: {
464
+ ...e.plugins?.entries,
465
+ [A]: {
466
+ ...e.plugins?.entries?.[A],
467
+ config: {
468
+ ...e.plugins?.entries?.[A]?.config,
469
+ user: void 0
470
+ }
471
+ }
472
+ }
473
+ }
474
+ };
475
+ await this.saveConfig(t);
476
+ } catch (e) {
477
+ throw E(e, "Failed to clear user config");
478
+ }
479
+ }
480
+ async initializePluginConfig(e) {
481
+ try {
482
+ let t = this.loadConfig(), n = t.plugins?.allow || [], r = n.includes(e) ? n : [...n, e], i = t.gateway?.nodes?.allowCommands || [], a = Array.from(new Set([...i, ...Pe])), o = t.skills || {}, s = o.load || {}, c = s.watch === Me.watch && s.watchDebounceMs !== void 0 ? s : {
483
+ ...s,
484
+ ...Me,
485
+ watchDebounceMs: s.watchDebounceMs ?? Ne
486
+ }, l = t.plugins?.entries?.[e]?.config?.envInfo, u = t.plugins?.entries?.[e]?.config?.env, d = !!(l?.env || u), f = be(), p = !!l?.env && l.source === "env", m = !l?.env && !!u || p && f && l.env !== f, ee = !d || m, te = {
487
+ env: f || u || (de() ? "test" : "production"),
488
+ source: "env"
489
+ }, ne = t.plugins?.entries?.[e]?.config || {}, re = ee ? {
490
+ ...ne,
491
+ envInfo: te,
492
+ env: void 0
493
+ } : ne, h = Ce(t);
494
+ Object.keys(h).length > 0 && D().info(`[claw-configs] Found ${Object.keys(h).length} providers to rename: ${Object.entries(h).map(([e, t]) => `${e} -> ${t}`).join(", ")}`);
495
+ let g = {
496
+ ...t,
497
+ plugins: {
498
+ ...t.plugins,
499
+ allow: r,
500
+ entries: {
501
+ ...t.plugins?.entries,
502
+ [e]: {
503
+ ...t.plugins?.entries?.[e],
504
+ enabled: !0,
505
+ config: re
506
+ }
507
+ }
508
+ },
509
+ gateway: {
510
+ ...t.gateway,
511
+ nodes: {
512
+ ...t.gateway?.nodes,
513
+ allowCommands: a
514
+ }
515
+ },
516
+ skills: {
517
+ ...o,
518
+ load: c
519
+ }
520
+ };
521
+ Object.keys(h).length > 0 && (g = we(g, h), D().info("[claw-configs] Provider renaming completed")), await this.saveConfig(g);
522
+ } catch (e) {
523
+ throw E(e, "failed to initialize plugin config");
524
+ }
525
+ }
526
+ }, Ie = null;
527
+ function j() {
528
+ return Ie ||= new Fe(), Ie;
529
+ }
530
+ //#endregion
531
+ //#region src/commands/env/impl.ts
532
+ var Le = {
533
+ env: "environment variable",
534
+ manual: "manual config"
535
+ };
536
+ function Re(e, t) {
537
+ return t.command("env").description("Manage runtime environment (dev/test/production)").option("--set <env>", "Set environment: dev, test or production").option("--gray <tag>", "Set gray header").option("--reset", "Reset env source to environment variable").action(async (e) => {
538
+ let { set: t, gray: n, reset: r } = e, i = D();
539
+ try {
540
+ let e = j();
541
+ if (r && (await e.resetEnv(), i.info("✅ Environment source reset to environment variable")), t) {
542
+ if (t !== "test" && t !== "dev" && t !== "production") {
543
+ i.error("❌ Invalid environment. Use 'test' or 'production'.");
544
+ return;
545
+ }
546
+ await e.updateEnv(t), i.info(`✅ Environment set to: ${t}`);
547
+ }
548
+ if (n ? (await e.updateGrayTag(n), i.info(`✅ Gray tag set to: ${n}`)) : n === "" && (await e.updateGrayTag(void 0), i.info("✅ Gray tag cleared")), !t && n === void 0) {
549
+ let t = e.getEnvInfo(), n = e.getGrayTag();
550
+ i.info(`📋 Current environment: ${t.env} (source: ${Le[t.source]})`), n ? i.info(`📋 Current gray tag: ${n}`) : i.info("📋 Gray tag: not set");
551
+ }
552
+ } catch (e) {
553
+ let t = e instanceof Error ? e.message : String(e);
554
+ i.error(`❌ Failed to manage environment: ${t}`);
555
+ }
556
+ });
557
+ }
558
+ //#endregion
559
+ //#region src/utils/id.ts
560
+ var ze = f("0123456789abcdefghijklmnopqrstuvwxyz", 32);
561
+ function M(e) {
562
+ return ze(e);
563
+ }
564
+ //#endregion
565
+ //#region src/apis/helpers.ts
566
+ function Be(e) {
567
+ return e.status >= 200 && e.status < 300 && e.data.code === "1";
568
+ }
569
+ //#endregion
570
+ //#region src/apis/hosts.ts
571
+ function Ve() {
572
+ let e = he(), t;
573
+ switch (e.env) {
574
+ case "dev":
575
+ t = {
576
+ clawCloud: "omni-dev-drcn.hiboard.hihonorcloud.com",
577
+ ics: "api-agd-test-drcn.hiboard.hihonorcloud.com"
578
+ };
579
+ break;
580
+ case "test":
581
+ t = {
582
+ clawCloud: "omni-pre-drcn.hiboard.hihonorcloud.com",
583
+ ics: "api-agd-test-drcn.hiboard.hihonorcloud.com"
584
+ };
585
+ break;
586
+ default:
587
+ t = {
588
+ clawCloud: "yoyoclaw-drcn.hiboard.hihonorcloud.com",
589
+ ics: "api-prd-drcn.hiboard.hihonorcloud.com"
590
+ };
591
+ break;
592
+ }
593
+ return e.grayTag && (t.grayTag = e.grayTag), t;
594
+ }
595
+ //#endregion
596
+ //#region src/utils/proxy.ts
597
+ function He(e) {
598
+ return e || process.env.HTTP_PROXY || process.env.http_proxy || process.env.HTTPS_PROXY || process.env.https_proxy;
599
+ }
600
+ function Ue(e, t) {
601
+ return !t && !!e;
602
+ }
603
+ function We(e, t) {
604
+ let n = He(t);
605
+ if (n) {
606
+ if (e.startsWith("wss://")) return new te(n);
607
+ if (e.startsWith("ws://")) return new ee(n);
608
+ }
609
+ }
610
+ //#endregion
611
+ //#region src/apis/http-client.ts
612
+ var Ge = class extends Error {
613
+ constructor(e, t, n) {
614
+ super(n), this.status = e, this.data = t, this.name = "HttpError";
615
+ }
616
+ }, Ke = class {
617
+ baseUrl;
618
+ defaultHeaders;
619
+ defaultTimeout;
620
+ proxyAgent;
621
+ constructor(e, t) {
622
+ this.baseUrl = e.replace(/\/$/, ""), this.defaultHeaders = t?.defaultHeaders || {}, this.defaultTimeout = t?.defaultTimeout || 3e4;
623
+ let n = He(t?.proxy);
624
+ n && (this.proxyAgent = new p(n));
625
+ }
626
+ async request(e) {
627
+ let { method: t = "GET", headers: n = {}, body: r, timeout: i = this.defaultTimeout, query: a } = e, o = e.url;
628
+ if (!o.startsWith("http://") && !o.startsWith("https://") && (o = `${this.baseUrl}${o.startsWith("/") ? "" : "/"}${o}`), a && Object.keys(a).length > 0) {
629
+ let e = new URLSearchParams();
630
+ Object.entries(a).forEach(([t, n]) => {
631
+ n !== void 0 && e.append(t, String(n));
632
+ });
633
+ let t = e.toString();
634
+ t && (o += (o.includes("?") ? "&" : "?") + t);
635
+ }
636
+ let s = {
637
+ ...this.defaultHeaders,
638
+ ...n
639
+ };
640
+ r && !s["Content-Type"] && (s["Content-Type"] = "application/json");
641
+ let c;
642
+ r != null && (c = typeof r == "string" ? r : JSON.stringify(r));
643
+ try {
644
+ let n = Ue(He(), e.disableProxy) && this.proxyAgent ? this.proxyAgent : void 0, r = await m(o, {
645
+ method: t,
646
+ headers: s,
647
+ body: c,
648
+ headersTimeout: i,
649
+ bodyTimeout: i,
650
+ dispatcher: n
651
+ }), a = await r.body.text(), l;
652
+ try {
653
+ l = a ? JSON.parse(a) : {};
654
+ } catch {
655
+ l = a;
656
+ }
657
+ if (r.statusCode >= 200 && r.statusCode < 300) return {
658
+ data: l,
659
+ status: r.statusCode,
660
+ headers: r.headers
661
+ };
662
+ throw new Ge(r.statusCode, l, `HTTP request failed with status ${r.statusCode}`);
663
+ } catch (e) {
664
+ throw e instanceof Ge ? e : E(e, "HTTP request failed");
665
+ }
666
+ }
667
+ async get(e, t) {
668
+ return this.request({
669
+ ...t,
670
+ url: e,
671
+ method: "GET"
672
+ });
673
+ }
674
+ async post(e, t) {
675
+ return this.request({
676
+ ...t,
677
+ url: e,
678
+ method: "POST"
679
+ });
680
+ }
681
+ async put(e, t) {
682
+ return this.request({
683
+ ...t,
684
+ url: e,
685
+ method: "PUT"
686
+ });
687
+ }
688
+ async delete(e, t) {
689
+ return this.request({
690
+ ...t,
691
+ url: e,
692
+ method: "DELETE"
693
+ });
694
+ }
695
+ async patch(e, t) {
696
+ return this.request({
697
+ ...t,
698
+ url: e,
699
+ method: "PATCH"
700
+ });
701
+ }
702
+ }, qe = class {
703
+ httpClient;
704
+ constructor(e, t) {
705
+ this.httpClient = new Ke(e, t);
706
+ }
707
+ async registerDevice(e, t, n) {
708
+ let r = {
709
+ "x-trace-id": M(),
710
+ "x-jwt-token": t.token,
711
+ "x-device-id": e.deviceId
712
+ }, i = {
713
+ businessTag: "YOYO_CLAW",
714
+ role: "yoyoclaw",
715
+ deviceInfo: {
716
+ ...e,
717
+ manufacture: e.manufacture,
718
+ brand: e.brand,
719
+ bizExtInfo: n
720
+ }
721
+ };
722
+ return this.httpClient.post("/v1/device/registry", {
723
+ headers: r,
724
+ body: i
725
+ });
726
+ }
727
+ async logoutDevice(e, t) {
728
+ let n = {
729
+ "x-trace-id": M(),
730
+ "x-jwt-token": t.token,
731
+ "x-device-id": e.deviceId
732
+ }, r = {
733
+ businessTag: "YOYO_CLAW",
734
+ deviceInfo: {
735
+ ...e,
736
+ manufacture: e.manufacture,
737
+ brand: e.brand
738
+ }
739
+ };
740
+ return this.httpClient.post("/v1/user/logout", {
741
+ headers: n,
742
+ body: r
743
+ });
744
+ }
745
+ async exchangeToken(e, t) {
746
+ let n = M(), r = {
747
+ "Content-Type": "application/json",
748
+ "x-device-id": e.deviceId,
749
+ "x-trace-id": n
750
+ }, i = {};
751
+ "userId" in t ? r["x-agw-userId"] = t.userId : i = {
752
+ clientId: t.authConfig.clientId,
753
+ code: t.code,
754
+ redirectUri: "http://127.0.0.1:8081/deepLink"
755
+ };
756
+ let a = await this.httpClient.post("/v1/user/jwtToken", {
757
+ body: i,
758
+ headers: r,
759
+ timeout: 15e3
760
+ });
761
+ if (Be(a) && a.data.data) return a.data.data;
762
+ throw Error(`failed to get token: ${JSON.stringify(a.data)}, traceId: ${n}`);
763
+ }
764
+ };
765
+ function N() {
766
+ let e = Ve();
767
+ return new qe(`https://${e.clawCloud}/aicloud/yoyo-claw-service`, e.grayTag ? { defaultHeaders: { "x-gray": e.grayTag } } : void 0);
768
+ }
769
+ //#endregion
770
+ //#region src/honor-auth/assets/favicon.png
771
+ var Je = "data:image/png;base64,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", Ye = "<svg aria-hidden=\"true\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"32\" cy=\"32\" r=\"30\" fill=\"currentColor\" opacity=\"0.12\"/><circle cx=\"32\" cy=\"32\" r=\"21\" fill=\"currentColor\"/><path d=\"M22.5 32.5L29 39L42.5 25.5\" stroke=\"white\" stroke-width=\"4.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>", Xe = "<svg aria-hidden=\"true\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"32\" cy=\"32\" r=\"30\" fill=\"currentColor\" opacity=\"0.12\"/><circle cx=\"32\" cy=\"32\" r=\"21\" fill=\"currentColor\"/><path d=\"M24.5 24.5L39.5 39.5M39.5 24.5L24.5 39.5\" stroke=\"white\" stroke-width=\"4.5\" stroke-linecap=\"round\"/></svg>", Ze = { favicon: "/favicon.png" };
772
+ function P(e) {
773
+ return e.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&#39;");
774
+ }
775
+ function Qe(e) {
776
+ return !e || e.length === 0 ? "" : `<div class="details">${e.map((e) => `<div class="detail-item"><span class="detail-key">${P(e.key)}</span><span class="detail-value">${P(e.value)}</span></div>`).join("")}</div>`;
777
+ }
778
+ function F(e) {
779
+ let t = e.statusClass === "success" ? Ye : Xe;
780
+ return `<!doctype html>
781
+ <html lang="zh-CN">
782
+ <head>
783
+ <meta charset="UTF-8" />
784
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
785
+ <link rel="icon" type="image/png" href="data:image/png;base64,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" />
786
+ <title>${P(e.pageTitle)}</title>
787
+ <style>
788
+ :root {
789
+ color-scheme: light;
790
+ --surface: rgba(255, 255, 255, 0.94);
791
+ --text: #172033;
792
+ --muted: #667085;
793
+ --faint: #98a2b3;
794
+ --border: rgba(23, 32, 51, 0.1);
795
+ --shadow: 0 22px 70px rgba(31, 41, 55, 0.14);
796
+ --success: #168255;
797
+ --error: #d14343;
798
+ --accent: #2563eb;
799
+ }
800
+
801
+ * {
802
+ box-sizing: border-box;
803
+ }
804
+
805
+ body {
806
+ margin: 0;
807
+ min-height: 100vh;
808
+ display: grid;
809
+ place-items: center;
810
+ padding: 24px;
811
+ font-family:
812
+ "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
813
+ color: var(--text);
814
+ background:
815
+ linear-gradient(135deg, rgba(37, 99, 235, 0.09), transparent 34%),
816
+ linear-gradient(315deg, rgba(22, 130, 85, 0.12), transparent 38%),
817
+ #f6f8fb;
818
+ }
819
+
820
+ .card {
821
+ width: min(100%, 480px);
822
+ padding: 24px;
823
+ border-radius: 18px;
824
+ background: var(--surface);
825
+ border: 1px solid var(--border);
826
+ box-shadow: var(--shadow);
827
+ backdrop-filter: blur(10px);
828
+ text-align: center;
829
+ }
830
+
831
+ .brand {
832
+ display: flex;
833
+ align-items: center;
834
+ justify-content: center;
835
+ gap: 9px;
836
+ margin-bottom: 24px;
837
+ color: var(--text);
838
+ font-size: 15px;
839
+ font-weight: 700;
840
+ }
841
+
842
+ .brand-logo {
843
+ width: 26px;
844
+ height: 26px;
845
+ display: block;
846
+ border-radius: 8px;
847
+ }
848
+
849
+ .icon-wrap {
850
+ width: 96px;
851
+ height: 96px;
852
+ margin: 0 auto 20px;
853
+ border-radius: 50%;
854
+ display: grid;
855
+ place-items: center;
856
+ background: transparent;
857
+ }
858
+
859
+ .icon-wrap.success {
860
+ color: var(--success);
861
+ filter: drop-shadow(0 16px 28px rgba(22, 130, 85, 0.18));
862
+ }
863
+
864
+ .icon-wrap.error {
865
+ color: var(--error);
866
+ filter: drop-shadow(0 16px 28px rgba(209, 67, 67, 0.18));
867
+ }
868
+
869
+ .icon-wrap svg {
870
+ display: block;
871
+ width: 78px;
872
+ height: 78px;
873
+ }
874
+
875
+ h1 {
876
+ margin: 0;
877
+ font-size: 26px;
878
+ line-height: 1.2;
879
+ font-weight: 700;
880
+ }
881
+
882
+ .details {
883
+ margin: 18px 0 0;
884
+ padding: 0;
885
+ border-radius: 16px;
886
+ background: rgba(255, 255, 255, 0.72);
887
+ border: 1px solid rgba(29, 36, 51, 0.07);
888
+ overflow: hidden;
889
+ text-align: left;
890
+ }
891
+
892
+ .detail-item {
893
+ display: grid;
894
+ grid-template-columns: 64px minmax(0, 1fr);
895
+ gap: 10px;
896
+ padding: 12px 14px;
897
+ font-size: 13px;
898
+ line-height: 1.5;
899
+ }
900
+
901
+ .detail-item + .detail-item {
902
+ border-top: 1px solid rgba(29, 36, 51, 0.07);
903
+ }
904
+
905
+ .detail-key {
906
+ color: #7a808d;
907
+ }
908
+
909
+ .detail-value {
910
+ color: var(--text);
911
+ word-break: break-word;
912
+ }
913
+
914
+ .footer {
915
+ margin-top: 22px;
916
+ padding-top: 16px;
917
+ border-top: 1px solid rgba(29, 36, 51, 0.08);
918
+ }
919
+
920
+ .hint {
921
+ margin: 0;
922
+ font-size: 14px;
923
+ color: var(--muted);
924
+ line-height: 1.6;
925
+ }
926
+
927
+ .caption {
928
+ margin: 8px 0 0;
929
+ color: var(--faint);
930
+ font-size: 12px;
931
+ line-height: 1.5;
932
+ }
933
+
934
+ @media (max-width: 480px) {
935
+ body {
936
+ padding: 16px;
937
+ }
938
+
939
+ .card {
940
+ padding: 22px 18px 18px;
941
+ border-radius: 16px;
942
+ }
943
+
944
+ .brand {
945
+ margin-bottom: 22px;
946
+ }
947
+
948
+ h1 {
949
+ font-size: 23px;
950
+ }
951
+
952
+ .icon-wrap {
953
+ width: 84px;
954
+ height: 84px;
955
+ }
956
+
957
+ .icon-wrap svg {
958
+ width: 70px;
959
+ height: 70px;
960
+ }
961
+ }
962
+ </style>
963
+ </head>
964
+ <body>
965
+ <main class="card">
966
+ <div class="brand">
967
+ <span>YOYOClaw</span>
968
+ </div>
969
+ <div class="icon-wrap ${e.statusClass}">${t}</div>
970
+ <h1>${P(e.title)}</h1>
971
+ ${Qe(e.details)}
972
+ <div class="footer">
973
+ <p class="hint">${P(e.hintText)}</p>
974
+ <p class="caption">浏览器不会自动关闭当前页面,保留或稍后关闭都不影响登录结果。</p>
975
+ </div>
976
+ </main>
977
+ </body>
978
+ </html>`;
979
+ }
980
+ //#endregion
981
+ //#region src/honor-auth/callback-server.ts
982
+ var $e = { "favicon.png": Je };
983
+ function et(e, t) {
984
+ let n = $e[t];
985
+ if (!n) {
986
+ e.writeHead(404), e.end();
987
+ return;
988
+ }
989
+ let r = n.replace(/^data:image\/png;base64,/, ""), i = Buffer.from(r, "base64");
990
+ e.writeHead(200, {
991
+ "Content-Type": "image/png",
992
+ "Cache-Control": "public, max-age=3600"
993
+ }), e.end(i);
994
+ }
995
+ function tt(e) {
996
+ return new Promise((t, n) => {
997
+ let { port: r, timeout: i = 6e5, onCodeReceived: a, onError: o } = e, s = null, c = !1, l = !1, u = !1, d = () => {
998
+ c || (c = !0, s && clearTimeout(s), m.close());
999
+ }, f = (e) => {
1000
+ d(), o?.(e), u || (u = !0, n(e));
1001
+ }, p = (e = 120) => {
1002
+ setTimeout(() => {
1003
+ d();
1004
+ }, e);
1005
+ }, m = ne((e, t) => {
1006
+ try {
1007
+ let n = new re(e.url || "", `http://localhost:${r}`);
1008
+ if (e.method !== "GET") {
1009
+ t.writeHead(405, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
1010
+ pageTitle: "请求方式不支持",
1011
+ statusClass: "error",
1012
+ title: "不支持的请求方式",
1013
+ hintText: "请返回 OpenClaw 重新发起登录。"
1014
+ }));
1015
+ return;
1016
+ }
1017
+ if (n.pathname === "/favicon.ico" || n.pathname === Ze.favicon) {
1018
+ et(t, "favicon.png");
1019
+ return;
1020
+ }
1021
+ let i = n.searchParams.get("code") || "", o = n.searchParams.get("error") || "", s = n.searchParams.get("error_description") || n.searchParams.get("error_message") || "";
1022
+ i && !l ? (l = !0, t.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
1023
+ pageTitle: "授权成功",
1024
+ statusClass: "success",
1025
+ title: "登录已完成",
1026
+ hintText: "请返回 OpenClaw,登录流程会继续完成。"
1027
+ })), p(), a(i)) : o && !l ? (t.writeHead(400, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
1028
+ pageTitle: "授权失败",
1029
+ statusClass: "error",
1030
+ title: "未能完成授权",
1031
+ hintText: "请返回 OpenClaw 重新发起登录。",
1032
+ details: [{
1033
+ key: "错误码",
1034
+ value: o
1035
+ }, ...s ? [{
1036
+ key: "说明",
1037
+ value: s
1038
+ }] : []]
1039
+ })), setTimeout(() => {
1040
+ f(/* @__PURE__ */ Error(s ? `authorization failed: ${o} (${s})` : `authorization failed: ${o}`));
1041
+ }, 120)) : l ? (t.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
1042
+ pageTitle: "登录已完成",
1043
+ statusClass: "success",
1044
+ title: "授权已经处理完成",
1045
+ hintText: "请返回 OpenClaw,登录流程会继续完成。"
1046
+ }))) : (t.writeHead(400, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
1047
+ pageTitle: "授权失败",
1048
+ statusClass: "error",
1049
+ title: "回调参数不完整",
1050
+ hintText: "请返回 OpenClaw 重新发起登录。"
1051
+ })), setTimeout(() => {
1052
+ f(/* @__PURE__ */ Error("authorization failed: no code in callback"));
1053
+ }, 120));
1054
+ } catch (e) {
1055
+ console.error("authorize callback error:", e), t.writeHead(500, { "Content-Type": "text/html; charset=utf-8" }), t.end(F({
1056
+ pageTitle: "服务异常",
1057
+ statusClass: "error",
1058
+ title: "回调服务出现异常",
1059
+ hintText: "请返回 OpenClaw 后重新发起登录。"
1060
+ })), setTimeout(() => {
1061
+ f(/* @__PURE__ */ Error("authorization failed: callback server internal error"));
1062
+ }, 120);
1063
+ }
1064
+ });
1065
+ m.on("error", (e) => {
1066
+ f(e);
1067
+ }), m.listen(r, () => {
1068
+ s = setTimeout(() => {
1069
+ f(/* @__PURE__ */ Error("authorize timeout"));
1070
+ }, i);
1071
+ }), m.on("close", () => {
1072
+ s && clearTimeout(s), u || (u = !0, t());
1073
+ });
1074
+ });
1075
+ }
1076
+ //#endregion
1077
+ //#region src/honor-auth/config.ts
1078
+ var nt = {
1079
+ authHost: "https://hnoauth-login-test-drcn.cloud.honor.com",
1080
+ clientId: "221641491",
1081
+ redirectUri: "http://127.0.0.1:8081/deepLink",
1082
+ localPort: 8081,
1083
+ scope: "openid profile",
1084
+ reqClientType: "110",
1085
+ loginChannel: "99011000"
1086
+ }, rt = {
1087
+ authHost: "https://hnoauth-login-drcn.cloud.honor.com",
1088
+ clientId: "221000597",
1089
+ redirectUri: "http://127.0.0.1:8081/deepLink",
1090
+ localPort: 8081,
1091
+ scope: "openid profile",
1092
+ reqClientType: "110",
1093
+ loginChannel: "99011000"
1094
+ };
1095
+ function it(e) {
1096
+ return {
1097
+ ...he()?.env === "production" ? rt : nt,
1098
+ ...e
1099
+ };
1100
+ }
1101
+ //#endregion
1102
+ //#region src/honor-auth/honor-auth-client.ts
1103
+ var at = class {
1104
+ config;
1105
+ constructor(e) {
1106
+ this.config = e;
1107
+ }
1108
+ generateRandomString(e) {
1109
+ let t = ie(e), n = "";
1110
+ for (let r = 0; r < e; r++) n += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"[t[r] % 62];
1111
+ return n;
1112
+ }
1113
+ generateCodeVerifier(e = 128) {
1114
+ let t = ie(e), n = "";
1115
+ for (let r = 0; r < e; r++) n += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"[t[r] % 66];
1116
+ return n;
1117
+ }
1118
+ generateCodeChallenge(e) {
1119
+ return g("sha256").update(e).digest().toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1120
+ }
1121
+ generatePKCEParams() {
1122
+ let e = this.generateCodeVerifier();
1123
+ return {
1124
+ codeVerifier: e,
1125
+ codeChallenge: this.generateCodeChallenge(e)
1126
+ };
1127
+ }
1128
+ buildAuthUrl(e) {
1129
+ let t = new URLSearchParams({
1130
+ client_id: this.config.clientId,
1131
+ redirect_uri: this.config.redirectUri,
1132
+ scope: this.config.scope,
1133
+ response_type: "code",
1134
+ access_type: "offline",
1135
+ state: this.generateRandomString(16),
1136
+ reqClientType: this.config.reqClientType,
1137
+ loginChannel: this.config.loginChannel,
1138
+ code_challenge: e.codeChallenge,
1139
+ code_challenge_method: "S256"
1140
+ });
1141
+ return `${this.config.authHost}/oauth2/v3/authorize?${t.toString()}`;
1142
+ }
1143
+ getConfig() {
1144
+ return { ...this.config };
1145
+ }
1146
+ };
1147
+ function ot(e) {
1148
+ return new at(e);
1149
+ }
1150
+ //#endregion
1151
+ //#region src/utils/fs-safe.ts
1152
+ var I = class extends Error {
1153
+ code;
1154
+ constructor(e, t, n) {
1155
+ super(t, n), this.code = e, this.name = "SafeFsError";
1156
+ }
1157
+ }, st = new Set(["ENOENT", "ENOTDIR"]), ct = new Set([
1158
+ "ELOOP",
1159
+ "EINVAL",
1160
+ "ENOTSUP"
1161
+ ]);
1162
+ function lt(e) {
1163
+ return !!(e && typeof e == "object" && "code" in e);
1164
+ }
1165
+ function L(e) {
1166
+ return lt(e) && typeof e.code == "string" && st.has(e.code);
1167
+ }
1168
+ function ut(e) {
1169
+ return lt(e) && typeof e.code == "string" && ct.has(e.code);
1170
+ }
1171
+ function dt(e) {
1172
+ let t = u.win32.normalize(e);
1173
+ return t.startsWith("\\\\?\\") && (t = t.slice(4), t.toUpperCase().startsWith("UNC\\") && (t = `\\\\${t.slice(4)}`)), t.replaceAll("/", "\\").toLowerCase();
1174
+ }
1175
+ function R(e, t) {
1176
+ let n = u.resolve(e), r = u.resolve(t);
1177
+ if (process.platform === "win32") {
1178
+ let e = dt(n), t = dt(r), i = u.win32.relative(e, t);
1179
+ return i === "" || !i.startsWith("..") && !u.win32.isAbsolute(i);
1180
+ }
1181
+ let i = u.relative(n, r);
1182
+ return i === "" || !i.startsWith("..") && !u.isAbsolute(i);
1183
+ }
1184
+ function ft(e) {
1185
+ return e === 0 || e === 0n;
1186
+ }
1187
+ function z(e, t, n = process.platform) {
1188
+ return e.ino === t.ino ? e.dev === t.dev ? !0 : n === "win32" && (ft(e.dev) || ft(t.dev)) : !1;
1189
+ }
1190
+ var pt = process.platform !== "win32" && "O_NOFOLLOW" in c, mt = c.O_RDONLY | (pt ? c.O_NOFOLLOW : 0), ht = c.O_WRONLY | c.O_CREAT | c.O_EXCL | (pt ? c.O_NOFOLLOW : 0), gt = c.O_WRONLY | c.O_APPEND | (pt ? c.O_NOFOLLOW : 0), _t = (e) => e.endsWith(u.sep) ? e : e + u.sep;
1191
+ function vt(e, t) {
1192
+ if (!e.startsWith("~")) return e;
1193
+ let n = t ?? process.env.HOME ?? process.env.USERPROFILE ?? se.homedir();
1194
+ return n ? e.replace(/^~(?=$|[\\/])/, n) : e;
1195
+ }
1196
+ async function yt(e) {
1197
+ let t;
1198
+ try {
1199
+ t = await v.realpath(e.rootDir);
1200
+ } catch (e) {
1201
+ throw L(e) ? new I("not-found", "root dir not found") : e;
1202
+ }
1203
+ let n = _t(t), r = vt(e.relativePath), i = u.resolve(n, r);
1204
+ if (!R(n, i)) throw new I("outside-root", "file is outside workspace root");
1205
+ return {
1206
+ rootReal: t,
1207
+ rootWithSep: n,
1208
+ resolved: i
1209
+ };
1210
+ }
1211
+ async function bt(e, t) {
1212
+ try {
1213
+ if ((await v.lstat(e)).isDirectory()) throw new I("not-file", "not a file");
1214
+ } catch (e) {
1215
+ if (e instanceof I) throw e;
1216
+ }
1217
+ let n;
1218
+ try {
1219
+ n = await v.open(e, mt);
1220
+ } catch (e) {
1221
+ throw L(e) ? new I("not-found", "file not found") : ut(e) ? new I("symlink", "symlink open blocked", { cause: e }) : lt(e) && e.code === "EISDIR" ? new I("not-file", "not a file") : e;
1222
+ }
1223
+ try {
1224
+ let [r, i] = await Promise.all([n.stat(), v.lstat(e)]);
1225
+ if (i.isSymbolicLink()) throw new I("symlink", "symlink not allowed");
1226
+ if (!r.isFile()) throw new I("not-file", "not a file");
1227
+ if (t?.rejectHardlinks && r.nlink > 1) throw new I("invalid-path", "hardlinked path not allowed");
1228
+ if (!z(r, i)) throw new I("path-mismatch", "path changed during read");
1229
+ let a = await v.realpath(e), o = await v.stat(a);
1230
+ if (t?.rejectHardlinks && o.nlink > 1) throw new I("invalid-path", "hardlinked path not allowed");
1231
+ if (!z(r, o)) throw new I("path-mismatch", "path mismatch");
1232
+ return {
1233
+ handle: n,
1234
+ realPath: a,
1235
+ stat: r
1236
+ };
1237
+ } catch (e) {
1238
+ throw await n.close().catch(() => {}), e instanceof I ? e : L(e) ? new I("not-found", "file not found") : e;
1239
+ }
1240
+ }
1241
+ async function xt(e) {
1242
+ let { rootWithSep: t, resolved: n } = await yt(e), r = await bt(n);
1243
+ if (!R(t, r.realPath)) throw await r.handle.close().catch(() => {}), new I("outside-root", "file is outside workspace root");
1244
+ try {
1245
+ if (e.maxBytes !== void 0 && r.stat.size > e.maxBytes) throw new I("too-large", `file exceeds limit of ${e.maxBytes} bytes (got ${r.stat.size})`);
1246
+ return {
1247
+ buffer: await r.handle.readFile(),
1248
+ realPath: r.realPath,
1249
+ stat: r.stat
1250
+ };
1251
+ } finally {
1252
+ await r.handle.close().catch(() => {});
1253
+ }
1254
+ }
1255
+ function St(e) {
1256
+ let t = u.dirname(e), n = u.basename(e);
1257
+ return u.join(t, `.${n}.${process.pid}.${oe()}.tmp`);
1258
+ }
1259
+ async function Ct(e) {
1260
+ let t = await v.open(e.tempPath, ht, e.mode);
1261
+ try {
1262
+ return typeof e.data == "string" ? await t.writeFile(e.data, e.encoding ?? "utf8") : await t.writeFile(e.data), await t.stat();
1263
+ } finally {
1264
+ await t.close().catch(() => {});
1265
+ }
1266
+ }
1267
+ async function wt(e) {
1268
+ let t = _t(await v.realpath(e.rootDir)), n = await bt(e.targetPath, { rejectHardlinks: !0 });
1269
+ try {
1270
+ if (!z(n.stat, e.expectedStat)) throw new I("path-mismatch", "path changed during write");
1271
+ if (!R(t, n.realPath)) throw new I("outside-root", "file is outside workspace root");
1272
+ } finally {
1273
+ await n.handle.close().catch(() => {});
1274
+ }
1275
+ }
1276
+ async function B(e) {
1277
+ let { rootWithSep: t, resolved: n } = await yt(e);
1278
+ e.mkdir !== !1 && await v.mkdir(u.dirname(n), { recursive: !0 });
1279
+ let r = n, i = !1;
1280
+ try {
1281
+ let e = await v.realpath(n);
1282
+ if (!R(t, e)) throw new I("outside-root", "file is outside workspace root");
1283
+ r = e, i = !0;
1284
+ } catch (e) {
1285
+ if (e instanceof I || !L(e)) throw e;
1286
+ }
1287
+ let a = e.mode === "append";
1288
+ if (a && !i) throw new I("not-found", "cannot append to non-existent file");
1289
+ return a ? await Tt({
1290
+ ioPath: r,
1291
+ rootWithSep: t,
1292
+ data: e.data,
1293
+ encoding: e.encoding,
1294
+ maxBytes: e.maxBytes
1295
+ }) : await Et({
1296
+ ioPath: r,
1297
+ rootWithSep: t,
1298
+ rootDir: e.rootDir,
1299
+ data: e.data,
1300
+ encoding: e.encoding,
1301
+ existingFile: i,
1302
+ fileMode: 384
1303
+ });
1304
+ }
1305
+ async function Tt(e) {
1306
+ let t;
1307
+ try {
1308
+ t = await v.open(e.ioPath, gt);
1309
+ } catch (e) {
1310
+ throw L(e) ? new I("not-found", "file not found") : ut(e) ? new I("symlink", "symlink open blocked", { cause: e }) : e;
1311
+ }
1312
+ try {
1313
+ let n = await t.stat();
1314
+ if (!n.isFile()) throw new I("not-file", "path is not a regular file");
1315
+ let r = await v.lstat(e.ioPath);
1316
+ if (r.isSymbolicLink()) throw new I("symlink", "path is a symlink");
1317
+ if (!z(n, r)) throw new I("path-mismatch", "path changed during write");
1318
+ let i = await v.realpath(e.ioPath);
1319
+ if (!R(e.rootWithSep, i)) throw new I("outside-root", "file is outside workspace root");
1320
+ let a = typeof e.data == "string" ? Buffer.byteLength(e.data, e.encoding ?? "utf8") : e.data.length;
1321
+ if (e.maxBytes !== void 0 && n.size + a > e.maxBytes) throw new I("too-large", `file would exceed limit of ${e.maxBytes} bytes`);
1322
+ return typeof e.data == "string" ? await t.writeFile(e.data, e.encoding ?? "utf8") : await t.writeFile(e.data), {
1323
+ realPath: i,
1324
+ bytesWritten: a,
1325
+ created: !1
1326
+ };
1327
+ } finally {
1328
+ await t.close().catch(() => {});
1329
+ }
1330
+ }
1331
+ async function Et(e) {
1332
+ let t = null, n = e.ioPath;
1333
+ try {
1334
+ t = St(n);
1335
+ let r = await Ct({
1336
+ tempPath: t,
1337
+ data: e.data,
1338
+ encoding: e.encoding,
1339
+ mode: e.fileMode
1340
+ });
1341
+ await v.rename(t, n), t = null;
1342
+ try {
1343
+ await wt({
1344
+ rootDir: e.rootDir,
1345
+ targetPath: n,
1346
+ expectedStat: r
1347
+ });
1348
+ } catch (e) {
1349
+ throw new I("write-failed", `${JSON.stringify(e)}`);
1350
+ }
1351
+ return {
1352
+ realPath: n,
1353
+ bytesWritten: typeof e.data == "string" ? Buffer.byteLength(e.data, e.encoding ?? "utf8") : e.data.length,
1354
+ created: !e.existingFile
1355
+ };
1356
+ } finally {
1357
+ t && await v.rm(t, { force: !0 }).catch(() => {});
1358
+ }
1359
+ }
1360
+ //#endregion
1361
+ //#region src/utils/home-dir.ts
1362
+ function V(e) {
1363
+ return e?.trim() || void 0;
1364
+ }
1365
+ function Dt(e = import.meta.url) {
1366
+ let t = u.dirname(h(e));
1367
+ for (; t !== u.dirname(t);) {
1368
+ if (l(u.join(t, "package.json"))) return t;
1369
+ t = u.dirname(t);
1370
+ }
1371
+ return t;
1372
+ }
1373
+ function Ot(e = process.env, t = se.homedir) {
1374
+ let n = kt(e, t);
1375
+ return n ? u.resolve(n) : void 0;
1376
+ }
1377
+ function kt(e, t) {
1378
+ let n = V(e.OPENCLAW_HOME);
1379
+ if (n) {
1380
+ if (n === "~" || n.startsWith("~/") || n.startsWith("~\\")) {
1381
+ let r = V(e.HOME) ?? V(e.USERPROFILE) ?? At(t);
1382
+ return r ? n.replace(/^~(?=$|[\\/])/, r) : void 0;
1383
+ }
1384
+ return n;
1385
+ }
1386
+ return V(e.HOME) || V(e.USERPROFILE) || At(t);
1387
+ }
1388
+ function At(e) {
1389
+ try {
1390
+ return V(e());
1391
+ } catch {
1392
+ return;
1393
+ }
1394
+ }
1395
+ //#endregion
1396
+ //#region src/modules/configs/identity-persist.ts
1397
+ var jt = /* @__PURE__ */ function(e) {
1398
+ return e[e.LEGACY = 1] = "LEGACY", e[e.NEW = 2] = "NEW", e;
1399
+ }({}), Mt = ".openclaw", Nt = "yoyo", Pt = "identity.json";
1400
+ function Ft() {
1401
+ return u.join(Mt, Nt, Pt);
1402
+ }
1403
+ async function It(e) {
1404
+ let t = Ft();
1405
+ try {
1406
+ let n = (await xt({
1407
+ rootDir: e,
1408
+ relativePath: t,
1409
+ maxBytes: 10 * 1024
1410
+ })).buffer.toString("utf8"), r = JSON.parse(n);
1411
+ return typeof r != "object" || !r ? zt() : {
1412
+ ...zt(),
1413
+ ...r
1414
+ };
1415
+ } catch (e) {
1416
+ return D().warn(`[yoyo-identity] failed to read identity: ${e.message}`), null;
1417
+ }
1418
+ }
1419
+ async function Lt() {
1420
+ let e = Ot();
1421
+ return e ? await It(e) || null : (D().warn("[yoyo-identity] failed to find home dir"), null);
1422
+ }
1423
+ async function Rt(e) {
1424
+ let t = Ot();
1425
+ if (!t) return D().warn("[yoyo-identity] failed to find home dir"), null;
1426
+ let n = await It(t), r = {
1427
+ ...n,
1428
+ version: n?.version || jt.NEW
1429
+ };
1430
+ return e.legacyDeviceId && (r.legacyDeviceId = e.legacyDeviceId), e.deviceId && (r.deviceId = e.deviceId, r.publicKeyPem = e.publicKeyPem, r.privateKeyPem = e.privateKeyPem, r.createdAtMs = e.createdAtMs), e.version && (r.version = e.version), await B({
1431
+ rootDir: t,
1432
+ relativePath: Ft(),
1433
+ data: JSON.stringify(r, null, 2),
1434
+ encoding: "utf8",
1435
+ mkdir: !0
1436
+ }), r;
1437
+ }
1438
+ function zt() {
1439
+ return { version: jt.NEW };
1440
+ }
1441
+ //#endregion
1442
+ //#region src/modules/device/registry.ts
1443
+ async function Bt(e, t) {
1444
+ if (!e || !t) throw Error("设备信息或用户信息缺失");
1445
+ let n = j().getGatewayAuthConfig(), r = await N().registerDevice(e, t, n);
1446
+ if (!Be(r)) throw Error(`注册失败:${r.data?.cnMessage}`);
1447
+ }
1448
+ //#endregion
1449
+ //#region src/modules/device/identity.ts
1450
+ var H = Buffer.from("302a300506032b6570032100", "hex");
1451
+ function Vt(e) {
1452
+ return e.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/g, "");
1453
+ }
1454
+ function Ht(e) {
1455
+ let t = _.createPublicKey(e).export({
1456
+ type: "spki",
1457
+ format: "der"
1458
+ });
1459
+ return t.length === H.length + 32 && t.subarray(0, H.length).equals(H) ? t.subarray(H.length) : t;
1460
+ }
1461
+ function Ut(e) {
1462
+ let t = Ht(e);
1463
+ return _.createHash("sha256").update(t).digest("hex");
1464
+ }
1465
+ async function Wt() {
1466
+ let { publicKey: e, privateKey: t } = _.generateKeyPairSync("ed25519"), n = e.export({
1467
+ type: "spki",
1468
+ format: "pem"
1469
+ }).toString(), r = t.export({
1470
+ type: "pkcs8",
1471
+ format: "pem"
1472
+ }).toString();
1473
+ return {
1474
+ deviceId: Ut(n),
1475
+ publicKeyPem: n,
1476
+ privateKeyPem: r,
1477
+ createdAtMs: Date.now()
1478
+ };
1479
+ }
1480
+ async function Gt() {
1481
+ let e = await Lt();
1482
+ if (e && e.deviceId && e.publicKeyPem && e.privateKeyPem && e.createdAtMs) {
1483
+ let t = e.deviceId, n = Ut(e.publicKeyPem);
1484
+ return n && n !== e.deviceId && (await Rt({
1485
+ ...e,
1486
+ deviceId: n
1487
+ }), t = n), {
1488
+ deviceId: t,
1489
+ privateKeyPem: e.privateKeyPem,
1490
+ publicKeyPem: e.publicKeyPem,
1491
+ legacyDeviceId: e.legacyDeviceId,
1492
+ createdAtMs: e.createdAtMs
1493
+ };
1494
+ }
1495
+ let t = await Wt();
1496
+ return await Rt(t), t;
1497
+ }
1498
+ function Kt(e, t) {
1499
+ let n = _.createPrivateKey(e);
1500
+ return Vt(_.sign(null, Buffer.from(t, "utf8"), n));
1501
+ }
1502
+ function qt(e) {
1503
+ return Vt(Ht(e));
1504
+ }
1505
+ //#endregion
1506
+ //#region src/modules/device/providers/linux.ts
1507
+ function Jt(t) {
1508
+ try {
1509
+ return e.existsSync(t) ? e.readFileSync(t, "utf-8").trim() : "";
1510
+ } catch {
1511
+ return "";
1512
+ }
1513
+ }
1514
+ var Yt = class {
1515
+ async ensureInitialized() {}
1516
+ getLinuxDeviceModel() {
1517
+ return Jt("/sys/class/dmi/id/product_name") || Jt("/sys/class/dmi/id/board_name") || `${y.cpus()[0]?.model || "Linux PC"} (${y.arch()})`;
1518
+ }
1519
+ getLinuxDeviceName() {
1520
+ return `${y.hostname()} (${this.getLinuxDeviceModel()})`;
1521
+ }
1522
+ getDeviceName() {
1523
+ return this.getLinuxDeviceName();
1524
+ }
1525
+ getDeviceModel() {
1526
+ return this.getLinuxDeviceModel();
1527
+ }
1528
+ getDeviceBrand() {
1529
+ return "unknown";
1530
+ }
1531
+ getDeviceType() {
1532
+ return "pc";
1533
+ }
1534
+ }, Xt = class {
1535
+ async ensureInitialized() {}
1536
+ getMacOSDeviceModel() {
1537
+ return `${y.cpus()[0]?.model || "Mac"} (${y.machine?.() || y.arch()})`;
1538
+ }
1539
+ getMacOSDeviceName() {
1540
+ return `${y.hostname()} (${this.getMacOSDeviceModel()})`;
1541
+ }
1542
+ getDeviceName() {
1543
+ return this.getMacOSDeviceName();
1544
+ }
1545
+ getDeviceModel() {
1546
+ return this.getMacOSDeviceModel();
1547
+ }
1548
+ getDeviceBrand() {
1549
+ return "Apple";
1550
+ }
1551
+ getDeviceType() {
1552
+ return "pc";
1553
+ }
1554
+ }, Zt = le(ce), Qt = class {
1555
+ cache = {
1556
+ brand: "",
1557
+ model: "",
1558
+ device: ""
1559
+ };
1560
+ initPromise;
1561
+ constructor() {
1562
+ this.initPromise = this._initializeCache();
1563
+ }
1564
+ async ensureInitialized() {
1565
+ await this.initPromise;
1566
+ }
1567
+ async execAndroidCmd(e, t = 5e3) {
1568
+ try {
1569
+ let { stdout: n } = await Zt("/system/bin/sh", ["-c", e], {
1570
+ timeout: t,
1571
+ encoding: "utf-8"
1572
+ });
1573
+ return n.trim();
1574
+ } catch {
1575
+ return "";
1576
+ }
1577
+ }
1578
+ async _initializeCache() {
1579
+ try {
1580
+ let [e, t, n] = await Promise.all([
1581
+ this.execAndroidCmd("/system/bin/getprop ro.product.brand"),
1582
+ this.execAndroidCmd("/system/bin/getprop ro.product.model"),
1583
+ this.execAndroidCmd("/system/bin/getprop ro.product.device")
1584
+ ]);
1585
+ this.cache.brand = e || "", this.cache.model = t || "", this.cache.device = n || "";
1586
+ } catch {}
1587
+ }
1588
+ getAndroidDeviceModel() {
1589
+ if (this.cache.model) return this.cache.model;
1590
+ try {
1591
+ let t = "/system/build.prop";
1592
+ if (e.existsSync(t)) {
1593
+ let n = e.readFileSync(t, "utf8").match(/ro\.product\.model=(.*)/);
1594
+ if (n && n[1]) return n[1].trim();
1595
+ }
1596
+ } catch {}
1597
+ return `Android(${y.arch()})`;
1598
+ }
1599
+ getAndroidDeviceName() {
1600
+ return this.getAndroidDeviceModel();
1601
+ }
1602
+ getDeviceName() {
1603
+ return this.getAndroidDeviceName();
1604
+ }
1605
+ getDeviceModel() {
1606
+ return this.getAndroidDeviceModel();
1607
+ }
1608
+ getDeviceType() {
1609
+ return "pad";
1610
+ }
1611
+ getDeviceBrand() {
1612
+ return this.cache.brand.toLowerCase() === "honor" ? "HONOR" : "";
1613
+ }
1614
+ };
1615
+ //#endregion
1616
+ //#region src/modules/device/providers/windows.ts
1617
+ function U(e, t, n) {
1618
+ return new Promise((r) => {
1619
+ try {
1620
+ new b({
1621
+ hive: e,
1622
+ key: t
1623
+ }).get(n, (e, t) => {
1624
+ e || !t || !t.value ? r("") : r(String(t.value).trim());
1625
+ });
1626
+ } catch {
1627
+ r("");
1628
+ }
1629
+ });
1630
+ }
1631
+ function $t(e, t) {
1632
+ return new Promise((n) => {
1633
+ try {
1634
+ new b({
1635
+ hive: e,
1636
+ key: t
1637
+ }).values((e) => {
1638
+ n(!e);
1639
+ });
1640
+ } catch {
1641
+ n(!1);
1642
+ }
1643
+ });
1644
+ }
1645
+ var en = class {
1646
+ cache = { deviceBrand: "" };
1647
+ initPromise;
1648
+ constructor() {
1649
+ this.initPromise = this._initializeCache();
1650
+ }
1651
+ async ensureInitialized() {
1652
+ await this.initPromise;
1653
+ }
1654
+ async _initializeCache() {
1655
+ try {
1656
+ let [e, t, n, r] = await Promise.all([
1657
+ U(b.HKLM, "\\HARDWARE\\DESCRIPTION\\System", "SystemManufacturer"),
1658
+ U(b.HKLM, "\\HARDWARE\\DESCRIPTION\\System", "SystemBiosVendor"),
1659
+ U(b.HKLM, "\\HARDWARE\\DESCRIPTION\\System\\BIOS", "Vendor"),
1660
+ U(b.HKLM, "\\HARDWARE\\DESCRIPTION\\System\\BIOS", "SystemManufacturer")
1661
+ ]);
1662
+ [
1663
+ e,
1664
+ t,
1665
+ n,
1666
+ r
1667
+ ].find((e) => e && e.toLowerCase().includes("honor")) || await $t(b.HKLM, "\\SOFTWARE\\HONOR\\PCManager") ? this.cache.deviceBrand = "HONOR" : this.cache.deviceBrand = "";
1668
+ } catch {
1669
+ this.cache.deviceBrand = "";
1670
+ }
1671
+ }
1672
+ getWindowsDeviceModel() {
1673
+ return `Windows ${y.release()}`;
1674
+ }
1675
+ getWindowsDeviceName() {
1676
+ return `${y.hostname()} (${this.getWindowsDeviceModel()})`;
1677
+ }
1678
+ getDeviceName() {
1679
+ return this.getWindowsDeviceName();
1680
+ }
1681
+ getDeviceModel() {
1682
+ return this.getWindowsDeviceModel();
1683
+ }
1684
+ getDeviceBrand() {
1685
+ return this.cache.deviceBrand;
1686
+ }
1687
+ getDeviceType() {
1688
+ return "pc";
1689
+ }
1690
+ };
1691
+ //#endregion
1692
+ //#region src/modules/device/providers/index.ts
1693
+ function tn() {
1694
+ let e = process.platform;
1695
+ if (e === "win32") return "windows";
1696
+ if (e === "linux") {
1697
+ try {
1698
+ if (s.existsSync("/system/bin/getprop")) return "pad";
1699
+ } catch {}
1700
+ return "linux";
1701
+ }
1702
+ return e === "darwin" ? "macos" : "linux";
1703
+ }
1704
+ function nn() {
1705
+ switch (tn()) {
1706
+ case "pad": return new Qt();
1707
+ case "windows": return new en();
1708
+ case "linux": return new Yt();
1709
+ case "macos": return new Xt();
1710
+ default: return new Yt();
1711
+ }
1712
+ }
1713
+ //#endregion
1714
+ //#region src/modules/device/device-info.ts
1715
+ async function W() {
1716
+ let e = nn(), t = j();
1717
+ await e.ensureInitialized();
1718
+ let n = await Gt(), r = n.legacyDeviceId ?? n.deviceId, i = ve(), a = t.getDeviceConfig();
1719
+ D().debug?.(`[yoyoclaw-device] env: ${JSON.stringify(i)}, config: ${JSON.stringify(a)}`);
1720
+ let o = i.brand || a?.brand || e.getDeviceBrand() || "unknown", s = i.deviceType || a?.type || e.getDeviceType(), c = (i.manufacture || a?.manufacture || o).slice(0, 128), l = (a?.name || e.getDeviceName()).slice(0, 128), u = (a?.model || e.getDeviceModel()).slice(0, 128), d = {
1721
+ deviceId: r,
1722
+ deviceName: l,
1723
+ deviceType: s,
1724
+ deviceModel: u,
1725
+ brand: o,
1726
+ manufacture: c,
1727
+ port: t.getGatewayPort()
1728
+ }, f = i.brand || i.deviceType || i.manufacture ? "env" : "config";
1729
+ D().info(`[yoyoclaw-device] device info: ${JSON.stringify(d)} (source: ${f})`);
1730
+ let p = !!(i.brand && i.brand !== a?.brand || i.manufacture && i.manufacture !== a?.manufacture || i.deviceType && i.deviceType !== a?.type);
1731
+ if (!a || p) {
1732
+ let e = {
1733
+ brand: o,
1734
+ type: s,
1735
+ manufacture: c,
1736
+ name: l,
1737
+ model: u
1738
+ };
1739
+ t.updateDeviceConfig(e).catch((e) => {
1740
+ D().warn(`[yoyoclaw-device] failed to persist device config: ${String(e)}`);
1741
+ });
1742
+ }
1743
+ return d;
1744
+ }
1745
+ //#endregion
1746
+ //#region src/modules/device/helpers.ts
1747
+ function rn(e) {
1748
+ return typeof e == "string" && e.trim() || "";
1749
+ }
1750
+ function an(e) {
1751
+ return e.replace(/[A-Z]/g, (e) => String.fromCharCode(e.charCodeAt(0) + 32));
1752
+ }
1753
+ function on(e) {
1754
+ let t = rn(e);
1755
+ return t ? an(t) : "";
1756
+ }
1757
+ //#endregion
1758
+ //#region src/modules/device/auth.ts
1759
+ function sn(e) {
1760
+ let t = e.scopes.join(","), n = e.token ?? "", r = on(e.platform), i = on(e.deviceFamily);
1761
+ return [
1762
+ "v3",
1763
+ e.deviceId,
1764
+ e.clientId,
1765
+ e.clientMode,
1766
+ e.role,
1767
+ t,
1768
+ String(e.signedAtMs),
1769
+ n,
1770
+ e.nonce,
1771
+ r,
1772
+ i
1773
+ ].join("|");
1774
+ }
1775
+ //#endregion
1776
+ //#region src/modules/device/credential-builder.ts
1777
+ function cn(e) {
1778
+ let { deviceIdentity: t, clientName: n = "", clientMode: r = "cli", role: i = "operator", scopes: a = ["operator.admin"], platform: o = process.platform, deviceFamily: s, authToken: c = null, nonce: l, signedAtMs: u = Date.now() } = e;
1779
+ if (!t) return;
1780
+ let d = sn({
1781
+ deviceId: t.deviceId,
1782
+ clientId: n,
1783
+ clientMode: r,
1784
+ role: i,
1785
+ scopes: a,
1786
+ signedAtMs: u,
1787
+ token: c,
1788
+ nonce: l,
1789
+ platform: o,
1790
+ deviceFamily: s
1791
+ }), f = Kt(t.privateKeyPem, d);
1792
+ return {
1793
+ id: t.deviceId,
1794
+ publicKey: qt(t.publicKeyPem),
1795
+ signature: f,
1796
+ signedAt: u,
1797
+ nonce: l
1798
+ };
1799
+ }
1800
+ //#endregion
1801
+ //#region src/honor-auth/token-manager.ts
1802
+ async function ln(e, t = !0) {
1803
+ try {
1804
+ let n = j(), r = e.jwtToken;
1805
+ if (!r && e.userId) {
1806
+ let t = e.deviceInfo || await W();
1807
+ r = (await N().exchangeToken(t, { userId: e.userId })).jwtToken;
1808
+ }
1809
+ if (!r) throw Error("no token available");
1810
+ if (!t) return D().info("💾 token got, but not to save"), { token: r };
1811
+ let i = Math.floor(Date.now() / 1e3) + 720 * 60 * 60;
1812
+ return await n.updateUserConfig({
1813
+ token: r,
1814
+ userId: void 0,
1815
+ expired: i
1816
+ }), { token: r };
1817
+ } catch (e) {
1818
+ throw E(e, "保存Token失败");
1819
+ }
1820
+ }
1821
+ async function un(e) {
1822
+ let t = await W(), n = await N().exchangeToken(t, { userId: e });
1823
+ if (n.jwtToken) {
1824
+ let e = Math.floor(Date.now() / 1e3) + 720 * 60 * 60;
1825
+ return await j().updateUserConfig({
1826
+ token: n.jwtToken,
1827
+ userId: void 0,
1828
+ userName: void 0,
1829
+ expired: e
1830
+ }), { token: n.jwtToken };
1831
+ }
1832
+ return await j().clearUserConfig(), null;
1833
+ }
1834
+ async function dn() {
1835
+ let e = D();
1836
+ try {
1837
+ let t = j(), n = t.getUserConfig(), r = ye();
1838
+ if (e.debug?.(`[yoyoclaw-auth] env userId: ${r ? "present" : "absent"}, config userId: ${n?.userId ? "present" : "absent"}, config token: ${n?.token ? "present" : "absent"}`), n?.userId) return await un(r || n.userId);
1839
+ if (n?.token) {
1840
+ if (!n.expired || n.expired >= Math.floor(Date.now() / 1e3)) return { token: n.token };
1841
+ e.debug?.("[yoyoclaw-auth] cached token expired");
1842
+ }
1843
+ return r ? (e.debug?.("[yoyoclaw-auth] token expired, using env userId to exchange token"), await un(r)) : (n?.token && (e.debug?.("[yoyoclaw-auth] clearing expired token"), await t.clearUserConfig()), null);
1844
+ } catch (e) {
1845
+ throw E(e, "加载Token失败");
1846
+ }
1847
+ }
1848
+ async function fn() {
1849
+ try {
1850
+ await j().clearUserConfig(), D().info("[yoyoclaw-auth] token cleared");
1851
+ } catch (e) {
1852
+ throw E(e, "清除Token失败");
1853
+ }
1854
+ }
1855
+ //#endregion
1856
+ //#region src/honor-auth/browser.ts
1857
+ async function pn(e, t) {
1858
+ let n = it(t);
1859
+ D().debug?.("Starting Honor login flow...");
1860
+ let r = ot(n), i = r.generatePKCEParams(), a = r.buildAuthUrl(i), o = null, s = tt({
1861
+ port: n.localPort,
1862
+ timeout: 6e5,
1863
+ onCodeReceived: (e) => {
1864
+ o = e;
1865
+ },
1866
+ onError: (e) => {
1867
+ console.error("callback server error:", e);
1868
+ }
1869
+ });
1870
+ console.log("🌐 open browser...");
1871
+ try {
1872
+ await d(a);
1873
+ } catch (e) {
1874
+ throw E(e, "failed to open browser, check your permissions");
1875
+ }
1876
+ try {
1877
+ await s;
1878
+ } catch (e) {
1879
+ throw E(e, "authorization timeout");
1880
+ }
1881
+ if (!o) throw Error("no auth code");
1882
+ try {
1883
+ let t = await N().exchangeToken(e, {
1884
+ code: o,
1885
+ authConfig: n
1886
+ });
1887
+ if (!t?.jwtToken) throw Error("failed to get jwt token");
1888
+ return await ln({ jwtToken: t.jwtToken }, n.saveToFile !== !1), { token: t.jwtToken };
1889
+ } catch (e) {
1890
+ throw E(e, "get token failed");
1891
+ }
1892
+ }
1893
+ //#endregion
1894
+ //#region src/honor-auth/cloud.ts
1895
+ async function mn() {
1896
+ let e = j().getUserConfig();
1897
+ if (!e?.token) throw Error("⚠️ Not logged in");
1898
+ let t = await W(), n = N(), r = { token: e.token }, i = await n.logoutDevice(t, r);
1899
+ if (!Be(i)) throw Error(i.data?.cnMessage || "Unknown error");
1900
+ await fn();
1901
+ }
1902
+ //#endregion
1903
+ //#region src/modules/login/impl.ts
1904
+ async function hn(e = {}) {
1905
+ let { userId: t } = e, n = D();
1906
+ try {
1907
+ n.debug?.("Starting login process...");
1908
+ let e = await W(), r;
1909
+ t ? (r = await ln({
1910
+ userId: t,
1911
+ deviceInfo: e
1912
+ }), n.debug?.("Using provided user info"), n.debug?.(`User: ${t}`), n.debug?.(`Device ID: ${e?.deviceId}`)) : (n.debug?.("Starting OAuth2 authentication..."), r = await pn(e), n.debug?.("OAuth2 authentication successful"), n.debug?.(`Device ID: ${e?.deviceId}`)), console.log("📡 Registering device to Claw Cloud..."), await Bt(e, r), console.log("✅ Device registered successfully"), console.log("🔗 Channel connection in progress, use 'openclaw honor status' to check device status");
1913
+ } catch (e) {
1914
+ let t = e instanceof Error ? e.message : String(e);
1915
+ console.error("❌ Login process failed:", t);
1916
+ }
1917
+ }
1918
+ //#endregion
1919
+ //#region src/commands/login/impl.ts
1920
+ function gn(e, t) {
1921
+ let n = t.command("login").description("login to yoyoclaw and register devices");
1922
+ return n = n.option("-u, --uid <userId>", "user ID for direct login").option("--token <token>", "token for direct login").action(async (t) => {
1923
+ let { uid: n, token: r } = t;
1924
+ e.logger.debug?.("honor login CLI command called"), await hn({
1925
+ userId: n,
1926
+ token: r
1927
+ });
1928
+ }), n;
1929
+ }
1930
+ //#endregion
1931
+ //#region src/commands/logout/impl.ts
1932
+ function _n(e, t) {
1933
+ return t.command("logout").description("Logout and clear user configuration").action(async () => {
1934
+ e.logger.info("logout CLI command called");
1935
+ try {
1936
+ await mn(), console.log("✅ Logout successful, gateway will automatically restart to handle new configuration");
1937
+ } catch (e) {
1938
+ let t = e instanceof Error ? e.message : String(e);
1939
+ console.error("❌ Logout failed:", t);
1940
+ }
1941
+ });
1942
+ }
1943
+ //#endregion
1944
+ //#region src/services/connection/status-tracker/events.ts
1945
+ var G = /* @__PURE__ */ function(e) {
1946
+ return e.CLOUD_SOCKET_CONNECTING = "cloud_socket_connecting", e.CLOUD_SOCKET_CONNECTED = "cloud_socket_connected", e.CLOUD_SOCKET_DISCONNECTED = "cloud_socket_disconnected", e.CLOUD_SOCKET_ERROR = "cloud_socket_error", e.CLOUD_SOCKET_RETRY = "cloud_socket_retry", e.GATEWAY_CLIENT_CONNECTED = "gateway_client_connected", e.GATEWAY_CLIENT_DISCONNECTED = "gateway_client_disconnected", e.ADMIN_CLIENT_RECONNECT_FAILED = "admin_client_reconnect_failed", e.DEVICE_PAIRING = "device_pairing", e.DEVICE_UNPAIRING = "device_unpairing", e.CONNECTION_STATUS_CHANGED = "connection_status_changed", e;
1947
+ }({}), vn = class {
1948
+ statusFilePath;
1949
+ statusDir;
1950
+ constructor() {
1951
+ let e = Dt();
1952
+ this.statusDir = r.join(e, ".yoyo-cache"), this.statusFilePath = r.join(this.statusDir, "yoyo-status.json");
1953
+ }
1954
+ async save(e) {
1955
+ try {
1956
+ await t.mkdir(this.statusDir, { recursive: !0 });
1957
+ let n = JSON.stringify(e, null, 2);
1958
+ await t.writeFile(this.statusFilePath, n, "utf-8");
1959
+ } catch (e) {
1960
+ throw console.error(`[StatusStorage] Failed to save status: ${e instanceof Error ? e.message : String(e)}`), e;
1961
+ }
1962
+ }
1963
+ async load() {
1964
+ try {
1965
+ await t.access(this.statusFilePath);
1966
+ let e = await t.readFile(this.statusFilePath, "utf-8");
1967
+ return JSON.parse(e);
1968
+ } catch (e) {
1969
+ return e.code === "ENOENT" || console.error(`[StatusStorage] Failed to load status: ${e instanceof Error ? e.message : String(e)}`), null;
1970
+ }
1971
+ }
1972
+ async clear() {
1973
+ try {
1974
+ await t.unlink(this.statusFilePath);
1975
+ } catch (e) {
1976
+ if (e.code !== "ENOENT") throw console.error(`[StatusStorage] Failed to clear status: ${e instanceof Error ? e.message : String(e)}`), e;
1977
+ }
1978
+ }
1979
+ getFilePath() {
1980
+ return this.statusFilePath;
1981
+ }
1982
+ async exists() {
1983
+ try {
1984
+ return await t.access(this.statusFilePath), !0;
1985
+ } catch {
1986
+ return !1;
1987
+ }
1988
+ }
1989
+ };
1990
+ //#endregion
1991
+ //#region src/services/connection/status-tracker/types.ts
1992
+ function yn() {
1993
+ return {
1994
+ status: "idle",
1995
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1996
+ cloudSocket: {
1997
+ connected: !1,
1998
+ connectedAt: null,
1999
+ lastDisconnectedAt: null,
2000
+ retryCount: 0,
2001
+ lastError: null,
2002
+ lastErrorAt: null,
2003
+ lastRetryAt: null,
2004
+ url: "",
2005
+ readyState: 3
2006
+ },
2007
+ gateway: {
2008
+ totalConnections: 0,
2009
+ activeConnections: 0,
2010
+ connections: []
2011
+ },
2012
+ devices: {
2013
+ totalDevices: 0,
2014
+ uniqueHardwareDevices: 0,
2015
+ devices: []
2016
+ },
2017
+ history: {
2018
+ connectionCount: 0,
2019
+ disconnectionCount: 0,
2020
+ lastConnectionAt: null,
2021
+ lastDisconnectionAt: null
2022
+ }
2023
+ };
2024
+ }
2025
+ //#endregion
2026
+ //#region src/services/connection/status-tracker/tracker.ts
2027
+ var bn = class {
2028
+ currentStatus;
2029
+ storage;
2030
+ autoSave;
2031
+ saveTimer;
2032
+ constructor(e = !0) {
2033
+ this.currentStatus = yn(), this.storage = new vn(), this.autoSave = e, this.saveTimer = null;
2034
+ }
2035
+ async handleEvent(e) {
2036
+ let { type: t, timestamp: n, data: r } = e;
2037
+ switch (t) {
2038
+ case G.CLOUD_SOCKET_CONNECTING:
2039
+ this.handleCloudSocketConnecting(r, n);
2040
+ break;
2041
+ case G.CLOUD_SOCKET_CONNECTED:
2042
+ this.handleCloudSocketConnected(r, n);
2043
+ break;
2044
+ case G.CLOUD_SOCKET_DISCONNECTED:
2045
+ this.handleCloudSocketDisconnected(r, n);
2046
+ break;
2047
+ case G.CLOUD_SOCKET_ERROR:
2048
+ this.handleCloudSocketError(r, n);
2049
+ break;
2050
+ case G.CLOUD_SOCKET_RETRY:
2051
+ this.handleCloudSocketRetry(r, n);
2052
+ break;
2053
+ case G.GATEWAY_CLIENT_CONNECTED:
2054
+ this.handleGatewayClientConnected(r, n);
2055
+ break;
2056
+ case G.GATEWAY_CLIENT_DISCONNECTED:
2057
+ this.handleGatewayClientDisconnected(r, n);
2058
+ break;
2059
+ case G.DEVICE_PAIRING:
2060
+ this.handleDevicePairing(r, n);
2061
+ break;
2062
+ case G.DEVICE_UNPAIRING:
2063
+ this.handleDeviceUnpairing(r, n);
2064
+ break;
2065
+ case G.CONNECTION_STATUS_CHANGED:
2066
+ this.handleConnectionStatusChanged(r, n);
2067
+ break;
2068
+ case G.ADMIN_CLIENT_RECONNECT_FAILED: break;
2069
+ default: console.warn(`[StatusTracker] Unknown event type: ${t}`);
2070
+ }
2071
+ this.currentStatus.updatedAt = new Date(n).toISOString(), this.autoSave && this.scheduleSave();
2072
+ }
2073
+ getStatus() {
2074
+ return { ...this.currentStatus };
2075
+ }
2076
+ async loadStatus() {
2077
+ let e = await this.storage.load();
2078
+ return e && (this.currentStatus = e), this.getStatus();
2079
+ }
2080
+ async loadAndCleanStatus() {
2081
+ let e = await this.storage.load();
2082
+ if (e) {
2083
+ let t = e.cloudSocket, n = e.history;
2084
+ this.currentStatus = yn(), this.currentStatus.cloudSocket = t, this.currentStatus.history = n, this.currentStatus.cloudSocket.connected = !1, this.currentStatus.cloudSocket.readyState = 3, await this.saveStatus();
2085
+ }
2086
+ return this.getStatus();
2087
+ }
2088
+ async saveStatus() {
2089
+ await this.storage.save(this.currentStatus);
2090
+ }
2091
+ async clearStatus() {
2092
+ this.currentStatus = yn(), await this.storage.clear();
2093
+ }
2094
+ handleCloudSocketConnecting(e, t) {
2095
+ this.currentStatus.cloudSocket.url = e.url || "", this.currentStatus.cloudSocket.connected = !1;
2096
+ }
2097
+ handleCloudSocketConnected(e, t) {
2098
+ this.currentStatus.cloudSocket.connected = !0, this.currentStatus.cloudSocket.connectedAt = e.connectedAt, this.currentStatus.cloudSocket.readyState = 1, this.currentStatus.cloudSocket.url = e.url, this.currentStatus.cloudSocket.retryCount = 0, this.currentStatus.cloudSocket.lastError = null, this.currentStatus.history.connectionCount++, this.currentStatus.history.lastConnectionAt = e.connectedAt;
2099
+ }
2100
+ handleCloudSocketDisconnected(e, t) {
2101
+ this.currentStatus.cloudSocket.connected = !1, this.currentStatus.cloudSocket.lastDisconnectedAt = e.disconnectedAt, this.currentStatus.cloudSocket.readyState = 3, this.currentStatus.history.disconnectionCount++, this.currentStatus.history.lastDisconnectionAt = e.disconnectedAt;
2102
+ }
2103
+ handleCloudSocketError(e, t) {
2104
+ this.currentStatus.cloudSocket.lastError = e.error, this.currentStatus.cloudSocket.lastErrorAt = new Date(t).toISOString();
2105
+ }
2106
+ handleCloudSocketRetry(e, t) {
2107
+ this.currentStatus.cloudSocket.retryCount = e.retryCount, this.currentStatus.cloudSocket.lastRetryAt = new Date(t).toISOString(), e.lastError && (this.currentStatus.cloudSocket.lastError = e.lastError);
2108
+ }
2109
+ handleGatewayClientConnected(e, t) {
2110
+ let n = {
2111
+ sessionId: e.sessionId,
2112
+ hardwareDeviceId: e.hardwareDeviceId,
2113
+ connectedAt: e.connectedAt,
2114
+ deviceInfo: e.deviceInfo
2115
+ };
2116
+ this.currentStatus.gateway.connections.push(n), this.currentStatus.gateway.totalConnections++, this.currentStatus.gateway.activeConnections++, this.updateDeviceInfo(e.hardwareDeviceId, e.deviceInfo ?? null, t);
2117
+ }
2118
+ handleGatewayClientDisconnected(e, t) {
2119
+ let n = this.currentStatus.gateway.connections.findIndex((t) => t.sessionId === e.sessionId);
2120
+ n !== -1 && (this.currentStatus.gateway.connections.splice(n, 1), this.currentStatus.gateway.activeConnections--), this.updateDeviceInfo(e.hardwareDeviceId, null, t);
2121
+ }
2122
+ handleDevicePairing(e, t) {
2123
+ this.updateDeviceInfo(e.hardwareDeviceId, e.deviceInfo, t);
2124
+ }
2125
+ handleDeviceUnpairing(e, t) {
2126
+ let n = this.currentStatus.devices.devices.findIndex((t) => t.hardwareDeviceId === e.hardwareDeviceId);
2127
+ n !== -1 && (this.currentStatus.devices.devices.splice(n, 1), this.recalculateDeviceStats());
2128
+ }
2129
+ handleConnectionStatusChanged(e, t) {
2130
+ this.currentStatus.status = e.status;
2131
+ }
2132
+ updateDeviceInfo(e, t, n) {
2133
+ let r = this.currentStatus.devices.devices.find((t) => t.hardwareDeviceId === e);
2134
+ if (r) r.lastActiveAt = new Date(n).toISOString(), t && (r.deviceInfo = t);
2135
+ else {
2136
+ let r = {
2137
+ hardwareDeviceId: e,
2138
+ sessions: 0,
2139
+ lastActiveAt: new Date(n).toISOString(),
2140
+ deviceInfo: t ?? void 0
2141
+ };
2142
+ this.currentStatus.devices.devices.push(r);
2143
+ }
2144
+ this.recalculateDeviceStats();
2145
+ }
2146
+ recalculateDeviceStats() {
2147
+ this.currentStatus.devices.totalDevices = this.currentStatus.devices.devices.length, this.currentStatus.devices.uniqueHardwareDevices = this.currentStatus.devices.devices.length;
2148
+ for (let e of this.currentStatus.devices.devices) e.sessions = this.currentStatus.gateway.connections.filter((t) => t.hardwareDeviceId === e.hardwareDeviceId).length;
2149
+ }
2150
+ scheduleSave() {
2151
+ this.saveTimer && clearTimeout(this.saveTimer), this.saveTimer = setTimeout(async () => {
2152
+ try {
2153
+ await this.saveStatus();
2154
+ } catch (e) {
2155
+ console.error(`[StatusTracker] Failed to save status: ${e instanceof Error ? e.message : String(e)}`);
2156
+ }
2157
+ }, 100);
2158
+ }
2159
+ async destroy() {
2160
+ this.saveTimer &&= (clearTimeout(this.saveTimer), null), await this.saveStatus();
2161
+ }
2162
+ };
2163
+ //#endregion
2164
+ //#region src/commands/status/index.ts
2165
+ function xn(e, t) {
2166
+ return t.command("status").description("Show YOYOClaw connection status").action(async () => {
2167
+ if (e.logger.debug?.("YOYOClaw status CLI command called"), !await dn()) {
2168
+ console.log("❌ You need to login first. Please run: openclaw honor login");
2169
+ return;
2170
+ }
2171
+ let t = await new vn().load(), n = null;
2172
+ try {
2173
+ n = await W();
2174
+ } catch {}
2175
+ let r = j().getEnvInfo();
2176
+ Sn(t, n, r);
2177
+ });
2178
+ }
2179
+ function Sn(e, t, n) {
2180
+ if (!e) {
2181
+ console.log("\n❌ No status data available");
2182
+ return;
2183
+ }
2184
+ console.log("\n📡 Cloud Socket:");
2185
+ let r = e.cloudSocket, i = r.connected ? "✅" : "❌";
2186
+ if (console.log(` Status: ${i} ${r.connected ? "Connected" : "Disconnected"}`), r.connectedAt && console.log(` Connected at: ${K(r.connectedAt)}`), r.lastDisconnectedAt && console.log(` Last disconnected: ${K(r.lastDisconnectedAt)}`), console.log(` Retry count: ${r.retryCount}`), console.log(` Last error: ${r.lastError || "None"}`), console.log("\n🌐 Gateway Connections:"), console.log(` Total connections: ${e.gateway.totalConnections}`), console.log(` Active connections: ${e.gateway.activeConnections}`), e.gateway.connections.length > 0) {
2187
+ console.log(" ┌────────────────────────────┬────────────────────────────┬────────────┐"), console.log(" │ Session ID │ Hardware Device ID │ Connected │"), console.log(" ├────────────────────────────┼────────────────────────────┼────────────┤");
2188
+ for (let t of e.gateway.connections) {
2189
+ let e = wn(t.sessionId, 26), n = wn(t.hardwareDeviceId, 26), r = Cn(t.connectedAt);
2190
+ console.log(` │ ${e.padEnd(28)}│ ${n.padEnd(28)}│ ${r.padEnd(12)}│`);
2191
+ }
2192
+ console.log(" └────────────────────────────┴────────────────────────────┴────────────┘");
2193
+ }
2194
+ if (console.log("\n📱 Physical Devices:"), console.log(` Unique devices: ${e.devices.uniqueHardwareDevices}`), e.devices.devices.length > 0) {
2195
+ console.log(" ┌────────────────────────────┬─────────┬────────────┐"), console.log(" │ Hardware Device ID │ Sessions │ Last Active│"), console.log(" ├────────────────────────────┼─────────┼────────────┤");
2196
+ for (let t of e.devices.devices) {
2197
+ let e = wn(t.hardwareDeviceId, 26), n = String(t.sessions).padEnd(9), r = Cn(t.lastActiveAt);
2198
+ console.log(` │ ${e.padEnd(28)}│ ${n}│ ${r.padEnd(12)}│`);
2199
+ }
2200
+ console.log(" └────────────────────────────┴─────────┴────────────┘");
2201
+ }
2202
+ console.log("\n📈 Connection History:"), console.log(` Total connections: ${e.history.connectionCount}`), console.log(` Total disconnections: ${e.history.disconnectionCount}`), e.history.lastConnectionAt && console.log(` Last connection: ${K(e.history.lastConnectionAt)}`), e.history.lastDisconnectionAt && console.log(` Last disconnection: ${K(e.history.lastDisconnectionAt)}`), console.log("\n🖥️ Device Info:"), t ? (console.log(` Device ID: ${t.deviceId}`), console.log(` Name: ${t.deviceName || "N/A"}`), console.log(` Type: ${t.deviceType}`), console.log(` Model: ${t.deviceModel || "N/A"}`), console.log(` Brand: ${t.brand || "N/A"}`)) : console.log(" Unable to load device info"), console.log("\n🌍 Environment:"), console.log(` Env: ${n.env} (source: ${n.source})`);
2203
+ }
2204
+ function K(e) {
2205
+ let t = new Date(e);
2206
+ return `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")} ${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}:${String(t.getSeconds()).padStart(2, "0")}`;
2207
+ }
2208
+ function Cn(e) {
2209
+ let t = new Date(e);
2210
+ return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}:${String(t.getSeconds()).padStart(2, "0")}`;
2211
+ }
2212
+ function wn(e, t) {
2213
+ return e.length <= t ? e : e.substring(0, t - 3) + "...";
2214
+ }
2215
+ //#endregion
2216
+ //#region src/commands/index.ts
2217
+ function Tn(e) {
2218
+ e.registerCli((t) => {
2219
+ let n = t.program.command("honor").description("Commands for honor yoyoclaw");
2220
+ gn(e, n), xn(e, n), _n(e, n), de() && Re(e, n);
2221
+ }, { commands: ["honor"] });
2222
+ }
2223
+ //#endregion
2224
+ //#region src/modules/prompt/index.ts
2225
+ var En = " ## 手机控制规则\n\n - 涉及手机控制的任务时,必须强制调用 yoyo_phone_control 技能完成任务。\n - 手机是可直接操控的设备,你的职责是执行操作,而不是向用户解释如何操作。 \n - 多步骤任务需**按顺序多次调用**,不得合并。 \n", Dn = x.object({
2226
+ token: x.string().optional(),
2227
+ expired: x.number().optional(),
2228
+ userId: x.string().optional(),
2229
+ userName: x.string().optional()
2230
+ }), On = x.object({
2231
+ type: x.string().optional(),
2232
+ manufacture: x.string().optional(),
2233
+ brand: x.string().optional(),
2234
+ name: x.string().optional(),
2235
+ model: x.string().optional()
2236
+ }), kn = x.object({
2237
+ user: Dn.optional(),
2238
+ device: On.optional(),
2239
+ envInfo: x.object({
2240
+ env: x.enum([
2241
+ "dev",
2242
+ "test",
2243
+ "production"
2244
+ ]),
2245
+ source: x.enum(["env", "manual"])
2246
+ }).optional(),
2247
+ env: x.enum([
2248
+ "dev",
2249
+ "test",
2250
+ "production"
2251
+ ]).optional(),
2252
+ gray: x.string().optional()
2253
+ });
2254
+ //#endregion
2255
+ //#region src/utils/ws.ts
2256
+ function An(e, t = "utf8") {
2257
+ return typeof e == "string" ? e : C.isBuffer(e) ? e.toString(t) : Array.isArray(e) ? C.concat(e).toString(t) : e instanceof ArrayBuffer ? C.from(e).toString(t) : C.from(String(e)).toString(t);
2258
+ }
2259
+ //#endregion
2260
+ //#region src/gateway-client/client.ts
2261
+ var jn = class {
2262
+ ws = null;
2263
+ opts;
2264
+ closed = !1;
2265
+ constructor(e = {}) {
2266
+ this.opts = e;
2267
+ }
2268
+ getUrl() {
2269
+ return `ws://127.0.0.1:${j().getGatewayPort()}`;
2270
+ }
2271
+ isConnected() {
2272
+ return this.ws !== null && this.ws.readyState === ue.OPEN;
2273
+ }
2274
+ connect() {
2275
+ if (this.closed) return;
2276
+ let e = this.getUrl();
2277
+ this.ws = new ue(e, { maxPayload: 25 * 1024 * 1024 }), this.ws.on("open", () => {
2278
+ this.opts.onOpen?.(), this.onOpen();
2279
+ }), this.ws.on("message", async (e) => {
2280
+ let t = An(e);
2281
+ await this.opts.onMessage?.(t), await this.onMessage(t);
2282
+ }), this.ws.on("close", (e, t) => {
2283
+ let n = An(t);
2284
+ this.ws = null, this.onClose(e, n), this.opts.onClose?.(`code: ${e}, reason: ${n ?? ""}`);
2285
+ }), this.ws.on("error", (e) => {
2286
+ this.onError(e), this.opts.onClose?.(`socket error: ${e.message}`);
2287
+ });
2288
+ }
2289
+ stop() {
2290
+ this.closed = !0, this.ws?.close(), this.ws = null;
2291
+ }
2292
+ send(e) {
2293
+ if (!this.ws || this.ws.readyState !== ue.OPEN) throw Error("gateway not connected");
2294
+ this.ws.send(e);
2295
+ }
2296
+ onOpen() {}
2297
+ onMessage(e) {}
2298
+ onClose(e, t) {}
2299
+ onError(e) {}
2300
+ }, Mn = {
2301
+ WEBCHAT_UI: "webchat-ui",
2302
+ CONTROL_UI: "openclaw-control-ui",
2303
+ WEBCHAT: "webchat",
2304
+ CLI: "cli",
2305
+ GATEWAY_CLIENT: "gateway-client",
2306
+ MACOS_APP: "openclaw-macos",
2307
+ IOS_APP: "openclaw-ios",
2308
+ ANDROID_APP: "openclaw-android",
2309
+ NODE_HOST: "node-host",
2310
+ FINGERPRINT: "fingerprint",
2311
+ PROBE: "openclaw-probe"
2312
+ }, Nn = {
2313
+ WEBCHAT: "webchat",
2314
+ CLI: "cli",
2315
+ UI: "ui",
2316
+ BACKEND: "backend",
2317
+ NODE: "node",
2318
+ PROBE: "probe"
2319
+ }, q = /* @__PURE__ */ function(e) {
2320
+ return e.CONNECTION_FAILED = "CONNECTION_FAILED", e.AUTH_FAILED = "AUTH_FAILED", e.INVALID_REQUEST = "INVALID_REQUEST", e.PERMISSION_DENIED = "PERMISSION_DENIED", e.TIMEOUT = "TIMEOUT", e.UNKNOWN = "UNKNOWN", e;
2321
+ }({}), J = class extends Error {
2322
+ code;
2323
+ details;
2324
+ retryable;
2325
+ constructor(e, t, n, r) {
2326
+ super(t), this.name = "WebSocketClientError", this.code = e, this.details = n, this.retryable = r;
2327
+ }
2328
+ }, Pn = {
2329
+ role: "operator",
2330
+ scopes: [],
2331
+ clientId: Mn.CLI,
2332
+ displayName: "Protocol Client",
2333
+ clientMode: Nn.CLI
2334
+ }, Fn = 3e4, In = "1.0.0", Ln = "server", Rn = 2, zn = 1e3, Bn = class extends jn {
2335
+ protocolOpts;
2336
+ config;
2337
+ pendingRequests = /* @__PURE__ */ new Map();
2338
+ pendingTimers = /* @__PURE__ */ new Map();
2339
+ connected = !1;
2340
+ authenticated = !1;
2341
+ helloOk = null;
2342
+ debug;
2343
+ connectNonce = null;
2344
+ connectNonceTimer = null;
2345
+ reconnectAttempts = 0;
2346
+ reconnectTimer = null;
2347
+ isReconnecting = !1;
2348
+ constructor(e = {}, t = {}) {
2349
+ super(e), this.protocolOpts = e, this.config = {
2350
+ ...Pn,
2351
+ ...t
2352
+ }, this.debug = process.env.DEBUG_GATEWAY === "true";
2353
+ }
2354
+ onMessage(e) {
2355
+ try {
2356
+ this.logDebug("received", e);
2357
+ let t = JSON.parse(e);
2358
+ if (t.type === "event") {
2359
+ this.handleEvent(t);
2360
+ return;
2361
+ }
2362
+ if (t.type === "res") {
2363
+ this.handleResponse(t);
2364
+ return;
2365
+ }
2366
+ } catch (e) {
2367
+ this.logDebug("parse error", e);
2368
+ }
2369
+ }
2370
+ onClose(e, t) {
2371
+ this.connected = !1, this.authenticated = !1, this.helloOk = null, this.resetConnectNonce(), this.clearAllPending(), this.protocolOpts.onClose?.(t), this.scheduleReconnect();
2372
+ }
2373
+ handleEvent(e) {
2374
+ if (e.event === "connect.challenge") {
2375
+ let t = e.payload;
2376
+ t?.nonce ? (this.connectNonce = t.nonce, this.clearConnectNonceTimer(), this.sendConnect()) : D().error("[protocol-gateway] connect challenge missing nonce");
2377
+ }
2378
+ }
2379
+ clearConnectNonceTimer() {
2380
+ this.connectNonceTimer &&= (clearTimeout(this.connectNonceTimer), null);
2381
+ }
2382
+ resetConnectNonce() {
2383
+ this.clearConnectNonceTimer(), this.connectNonce = null;
2384
+ }
2385
+ handleResponse(e) {
2386
+ let t = this.pendingRequests.get(e.id);
2387
+ if (t) if (this.logDebug("response", e), this.pendingRequests.delete(e.id), this.clearTimer(e.id), e.ok) t.resolve(e.payload);
2388
+ else {
2389
+ let n = e.error || {
2390
+ code: q.UNKNOWN,
2391
+ message: "Unknown error"
2392
+ };
2393
+ t.reject(new J(this.toErrorCode(n.code), n.message, n.details, n.retryable));
2394
+ }
2395
+ }
2396
+ async sendConnect() {
2397
+ let e = this.config.clientMode ?? Nn.CLI, t = await Gt(), n = this.connectNonce ? cn({
2398
+ deviceIdentity: t,
2399
+ clientName: this.config.clientId,
2400
+ clientMode: e,
2401
+ role: this.config.role,
2402
+ scopes: this.config.scopes,
2403
+ authToken: this.protocolOpts.token,
2404
+ nonce: this.connectNonce,
2405
+ platform: process.platform,
2406
+ deviceFamily: Ln
2407
+ }) : void 0, r = {
2408
+ minProtocol: 3,
2409
+ maxProtocol: 3,
2410
+ client: {
2411
+ id: this.config.clientId,
2412
+ displayName: this.config.displayName,
2413
+ version: In,
2414
+ platform: process.platform,
2415
+ deviceFamily: Ln,
2416
+ mode: e
2417
+ },
2418
+ role: this.config.role,
2419
+ scopes: this.config.scopes,
2420
+ auth: { token: this.protocolOpts.token },
2421
+ device: n
2422
+ };
2423
+ this.sendRequest("connect", r).then((e) => {
2424
+ this.helloOk = e, this.connected = !0, this.authenticated = !0, this.protocolOpts.onAuthenticated?.();
2425
+ }).catch((e) => {
2426
+ this.authenticated = !1, e instanceof J ? this.protocolOpts.onClose?.(`auth failed: [${e.code}] ${e.message}`) : this.protocolOpts.onClose?.(`auth failed: ${e.message}`);
2427
+ });
2428
+ }
2429
+ async sendRequest(e, t) {
2430
+ let n = oe();
2431
+ return this.logDebug("request", {
2432
+ id: n,
2433
+ method: e,
2434
+ params: t
2435
+ }), new Promise((r, i) => {
2436
+ let a = {
2437
+ type: "req",
2438
+ id: n,
2439
+ method: e,
2440
+ params: t
2441
+ };
2442
+ this.pendingRequests.set(n, {
2443
+ resolve: r,
2444
+ reject: i
2445
+ });
2446
+ try {
2447
+ this.send(JSON.stringify(a));
2448
+ } catch (e) {
2449
+ this.pendingRequests.delete(n), i(new J(q.CONNECTION_FAILED, `WebSocket is not connected, ${JSON.stringify(e)}`));
2450
+ return;
2451
+ }
2452
+ let o = setTimeout(() => {
2453
+ if (this.pendingRequests.has(n)) {
2454
+ this.pendingRequests.delete(n);
2455
+ let t = this.pendingTimers.get(n);
2456
+ t && clearTimeout(t), this.pendingTimers.delete(n), i(new J(q.TIMEOUT, `Request timeout: ${e}`));
2457
+ }
2458
+ }, Fn);
2459
+ this.pendingTimers.set(n, o);
2460
+ });
2461
+ }
2462
+ isAuthenticated() {
2463
+ return this.authenticated;
2464
+ }
2465
+ isConnected() {
2466
+ return this.connected;
2467
+ }
2468
+ toErrorCode(e) {
2469
+ return Object.values(q).includes(e) ? e : q.UNKNOWN;
2470
+ }
2471
+ clearTimer(e) {
2472
+ let t = this.pendingTimers.get(e);
2473
+ t && (clearTimeout(t), this.pendingTimers.delete(e));
2474
+ }
2475
+ clearAllPending() {
2476
+ for (let e of this.pendingTimers.keys()) clearTimeout(this.pendingTimers.get(e));
2477
+ this.pendingTimers.clear(), this.pendingRequests.clear();
2478
+ }
2479
+ logDebug(e, t) {
2480
+ this.debug && D().info(`[yoyoclaw-protocolGatewayClient:${e}] ${JSON.stringify(t)}`);
2481
+ }
2482
+ connect() {
2483
+ this.closed || (this.isReconnecting = !1, super.connect());
2484
+ }
2485
+ stop() {
2486
+ this.isReconnecting = !1, this.reconnectTimer &&= (clearTimeout(this.reconnectTimer), null), this.reconnectAttempts = 0, super.stop();
2487
+ }
2488
+ scheduleReconnect() {
2489
+ if (!(this.closed || this.isReconnecting)) {
2490
+ if (this.reconnectAttempts >= Rn) {
2491
+ D().error(`[protocol-gateway] max reconnect attempts (${Rn}) reached, giving up`), this.protocolOpts.onReconnectFailed?.();
2492
+ return;
2493
+ }
2494
+ this.reconnectAttempts++, this.isReconnecting = !0, D().info(`[protocol-gateway] attempting to reconnect (attempt ${this.reconnectAttempts}/${Rn})`), this.reconnectTimer = setTimeout(() => {
2495
+ this.isReconnecting = !1, this.closed || super.connect();
2496
+ }, zn);
2497
+ }
2498
+ }
2499
+ }, Vn = {
2500
+ role: "operator",
2501
+ scopes: [
2502
+ "operator.admin",
2503
+ "operator.read",
2504
+ "operator.write",
2505
+ "operator.talk.secrets",
2506
+ "operator.approvals",
2507
+ "operator.pairing"
2508
+ ],
2509
+ clientId: Mn.CLI,
2510
+ displayName: "YOYO-Control",
2511
+ clientMode: Nn.BACKEND
2512
+ }, Hn = class extends Bn {
2513
+ constructor(e = {}) {
2514
+ super(e, Vn);
2515
+ }
2516
+ async setAgentFile(e, t, n = "main") {
2517
+ return this.sendRequest("agents.files.set", {
2518
+ agentId: n,
2519
+ name: e,
2520
+ content: t
2521
+ });
2522
+ }
2523
+ async getSkillsStatus() {
2524
+ return this.sendRequest("skills.status", {});
2525
+ }
2526
+ async getModelList() {
2527
+ return this.sendRequest("models.list", {});
2528
+ }
2529
+ async switchPrimaryModel(e, t) {
2530
+ return this.sendRequest("sessions.patch", {
2531
+ key: "agent:main:main",
2532
+ model: `${e}/${t}`
2533
+ });
2534
+ }
2535
+ async getMainSession() {
2536
+ return (await this.sendRequest("sessions.list", {
2537
+ includeGlobal: !0,
2538
+ includeUnknown: !0
2539
+ })).sessions?.find((e) => e?.key === "agent:main:main") ?? {};
2540
+ }
2541
+ async devicePairList() {
2542
+ return this.sendRequest("device.pair.list", {});
2543
+ }
2544
+ async devicePairApprove(e) {
2545
+ return this.sendRequest("device.pair.approve", { requestId: e });
2546
+ }
2547
+ }, Un = class {
2548
+ client = null;
2549
+ ready = !1;
2550
+ options;
2551
+ pendingReadyRequests = /* @__PURE__ */ new Map();
2552
+ requestIdCounter = 0;
2553
+ constructor(e = {}) {
2554
+ this.options = e;
2555
+ }
2556
+ init() {
2557
+ if (this.client !== null) return;
2558
+ let e = j().getGatewayAuthConfig()?.token || "";
2559
+ this.client = new Hn({
2560
+ token: e,
2561
+ onAuthenticated: () => {
2562
+ D().info("[yoyoclaw-channel] admin gateway client authenticated"), this.ready = !0, this.resolveAllPending(!0);
2563
+ },
2564
+ onClose: (e) => {
2565
+ D().info(`[yoyoclaw-channel] admin gateway client closed: ${e}`), this.ready = !1;
2566
+ },
2567
+ onReconnectFailed: () => {
2568
+ D().error("[yoyoclaw-channel] admin gateway client reconnect failed, notifying status tracker"), this.options.onStatusEvent?.({
2569
+ type: G.ADMIN_CLIENT_RECONNECT_FAILED,
2570
+ timestamp: Date.now(),
2571
+ data: {}
2572
+ });
2573
+ }
2574
+ });
2575
+ }
2576
+ connect() {
2577
+ this.client?.connect();
2578
+ }
2579
+ destroy() {
2580
+ this.client &&= (this.client.stop(), null), this.ready = !1, this.cancelAllPending(), D().info("[yoyoclaw-channel] admin gateway client closed");
2581
+ }
2582
+ cancelAllPending() {
2583
+ for (let [e, t] of this.pendingReadyRequests) clearTimeout(t.timeout), t.resolve(!1);
2584
+ this.pendingReadyRequests.clear();
2585
+ }
2586
+ isReady() {
2587
+ return this.ready;
2588
+ }
2589
+ getClient() {
2590
+ return this.client;
2591
+ }
2592
+ canOperate() {
2593
+ return this.client !== null && this.ready;
2594
+ }
2595
+ ensureConnected() {
2596
+ return this.client === null && (D().info("[yoyoclaw-channel] admin gateway client is null, initializing"), this.init()), this.ready || (D().info("[yoyoclaw-channel] admin gateway client not ready, connecting"), this.connect()), this.canOperate();
2597
+ }
2598
+ waitForReady(e = 5e3) {
2599
+ return this.canOperate() ? Promise.resolve(!0) : new Promise((t) => {
2600
+ let n = `req_${++this.requestIdCounter}`, r = setTimeout(() => {
2601
+ this.pendingReadyRequests.delete(n), this.pendingReadyRequests.size === 0 && D().warn("[yoyoclaw-channel] admin gateway client waitForReady timeout, all requests rejected"), t(!1);
2602
+ }, e);
2603
+ this.pendingReadyRequests.set(n, {
2604
+ resolve: t,
2605
+ timeout: r
2606
+ }), this.ensureConnected();
2607
+ });
2608
+ }
2609
+ resolveAllPending(e) {
2610
+ for (let [t, n] of this.pendingReadyRequests) clearTimeout(n.timeout), n.resolve(e);
2611
+ this.pendingReadyRequests.clear();
2612
+ }
2613
+ }, Wn = "/aicloud/yoyo-claw-service/v1/yoyoclaw/fullduplex", Gn = 25 * 1024 * 1024;
2614
+ function Kn(e, t) {
2615
+ let n = Ve(), r = n.grayTag ? { "x-gray": n.grayTag } : void 0, i = M(), a = `wss://${n.clawCloud}${Wn}`, o = qn(e, t, i, r), s = We(a), c = {
2616
+ headers: o,
2617
+ maxPayload: Gn
2618
+ };
2619
+ return s && (c.agent = s), {
2620
+ url: a,
2621
+ traceId: i,
2622
+ wsOptions: c
2623
+ };
2624
+ }
2625
+ function qn(e, t, n, r) {
2626
+ let i = {
2627
+ "x-role": "yoyoclaw",
2628
+ "x-trace-id": n,
2629
+ "x-jwt-token": t.token,
2630
+ "x-device-id": e.deviceId
2631
+ };
2632
+ return e.port !== void 0 && (i["x-port"] = String(e.port)), r && Object.assign(i, r), i;
2633
+ }
2634
+ //#endregion
2635
+ //#region src/cloud-channel/client.ts
2636
+ var Jn = 3e4, Yn = 4e3, Xn = 1e3, Zn = 2, Qn = 999, $n = class {
2637
+ ws = null;
2638
+ options;
2639
+ retryCount = 0;
2640
+ retryTimer = null;
2641
+ isManualClose = !1;
2642
+ isRetryPaused = !1;
2643
+ pingTimer = null;
2644
+ currentTraceId = "";
2645
+ constructor(e) {
2646
+ this.options = e;
2647
+ }
2648
+ connect(e = !1) {
2649
+ if (this.ws?.readyState === S.OPEN) return;
2650
+ this.clearRetryTimer();
2651
+ let { deviceInfo: t, userInfo: n } = this.options, { url: r, traceId: i, wsOptions: a } = Kn(t, n);
2652
+ this.currentTraceId = i, this.options.onStatusEvent?.({
2653
+ type: G.CLOUD_SOCKET_CONNECTING,
2654
+ timestamp: Date.now(),
2655
+ data: { url: r }
2656
+ }), this.ws = new S(r, a), this.ws.on("open", this.handleOpen.bind(this, r, e)), this.ws.on("message", this.onMessage), this.ws.on("pong", this.handlePong), this.ws.on("close", this.handleClose), this.ws.on("error", this.handleError);
2657
+ }
2658
+ handleOpen = (e, t) => {
2659
+ let n = t ? "reconnected" : "connected";
2660
+ D().info(`[claw-cloud-socket][${this.currentTraceId}] ${n} to ${e.slice(0, 15)}`), this.clearRetryTimer(), this.isManualClose = !1, this.retryCount = 0, this.isRetryPaused = !1, this.startPingTimer(), this.options.onStatusEvent?.({
2661
+ type: G.CLOUD_SOCKET_CONNECTED,
2662
+ timestamp: Date.now(),
2663
+ data: {
2664
+ url: e,
2665
+ connectedAt: (/* @__PURE__ */ new Date()).toISOString()
2666
+ }
2667
+ }), this.options.onOpen?.();
2668
+ };
2669
+ handlePong = () => {
2670
+ D().debug?.("[claw-cloud-socket] received pong from server");
2671
+ };
2672
+ handleClose = (e, t) => {
2673
+ let n = t.toString();
2674
+ D().info(`[claw-cloud-socket][${this.currentTraceId}] connection closed: ${e} - ${n}`), this.options.onStatusEvent?.({
2675
+ type: G.CLOUD_SOCKET_DISCONNECTED,
2676
+ timestamp: Date.now(),
2677
+ data: {
2678
+ reason: n,
2679
+ code: e,
2680
+ disconnectedAt: (/* @__PURE__ */ new Date()).toISOString()
2681
+ }
2682
+ }), this.isManualClose ? (this.stopPingTimer(), this.options.onClose?.()) : this.scheduleReconnect();
2683
+ };
2684
+ handleError = (e) => {
2685
+ D().error(`[claw-cloud-socket][${this.currentTraceId}] connect errorred: ${e.message}`), e.message.includes("401") && (D().warn(`[claw-cloud-socket][${this.currentTraceId}] unauthorized connection (401), pausing retry and notifying client`), this.pauseRetry(), this.options.onUnauthorized?.()), this.options.onStatusEvent?.({
2686
+ type: G.CLOUD_SOCKET_ERROR,
2687
+ timestamp: Date.now(),
2688
+ data: {
2689
+ error: e.message,
2690
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2691
+ }
2692
+ });
2693
+ };
2694
+ send(e) {
2695
+ if (!this.ws || this.ws.readyState !== S.OPEN) return D().error("[claw-cloud-socket] cannot send message: connection not open"), !1;
2696
+ try {
2697
+ let t = JSON.stringify(e);
2698
+ return this.ws.send(t), !0;
2699
+ } catch (t) {
2700
+ return D().error(`[claw-cloud-socket] failed to send message to cloud session ${e.targetDeviceId},
2701
+ ${t instanceof Error ? t.message : String(t)}`), !1;
2702
+ }
2703
+ }
2704
+ close() {
2705
+ this.isManualClose = !0, this.reset(), this.ws &&= (this.ws.close(), null);
2706
+ }
2707
+ reset() {
2708
+ this.clearRetryTimer(), this.stopPingTimer();
2709
+ }
2710
+ onMessage = async (e) => {
2711
+ try {
2712
+ let t = An(e), n = JSON.parse(t);
2713
+ if (D().debug?.(`[yoyoclaw-channel] received cloud message from session ${n.wsOutputEvent?.sourceDeviceId}, deviceId ${n.wsOutputEvent?.sourceDeviceInfo?.deviceId || "nil"}, ${t.slice(0, 1e3)}`), n.code === "YOYO_CLAW_100000") {
2714
+ if (n.wsOutputEvent) {
2715
+ n.sessionInfo && (n.wsOutputEvent.sessionInfo = n.sessionInfo), this.options.onMessage?.(n.wsOutputEvent);
2716
+ return;
2717
+ }
2718
+ } else if (n.code === "YOYO_CLAW_100002") {
2719
+ if (n.extData?.offlineSocketId) {
2720
+ D().info(`[claw-cloud-socket] remote device offline, session: ${n.extData.offlineSocketId}`), this.options.onRemoteDeviceOffline?.(n.extData.offlineSocketId);
2721
+ return;
2722
+ }
2723
+ } else if (n.code === "YOYO_CLAW_100001") {
2724
+ this.pauseRetry(), D().info("[claw-cloud-socket] device not registered, closing connection"), this.options.onDeviceNotRegistered?.();
2725
+ return;
2726
+ }
2727
+ D().warn(`[claw-cloud-socket] unexpected message: ${n.cnMessage}, code: ${n.code}`);
2728
+ } catch (e) {
2729
+ D().error(`[claw-cloud-socket] failed to parse message: ${e instanceof Error ? e.message : String(e)}`);
2730
+ }
2731
+ };
2732
+ scheduleReconnect() {
2733
+ if (this.isRetryPaused) {
2734
+ D().info("[claw-cloud-socket] retry paused, skipping reconnect"), this.reset(), this.options.onClose?.();
2735
+ return;
2736
+ }
2737
+ this.clearRetryTimer();
2738
+ let e = this.calculateRetryDelay();
2739
+ this.retryCount = Math.min(this.retryCount + 1, Qn), D().info(`[claw-cloud-socket] scheduling reconnect attempt ${this.retryCount} in ${e}ms`), this.options.onStatusEvent?.({
2740
+ type: G.CLOUD_SOCKET_RETRY,
2741
+ timestamp: Date.now(),
2742
+ data: {
2743
+ retryCount: this.retryCount,
2744
+ delay: e
2745
+ }
2746
+ }), this.retryTimer = setTimeout(() => {
2747
+ this.connect(!0);
2748
+ }, e);
2749
+ }
2750
+ clearRetryTimer() {
2751
+ this.retryTimer &&= (clearTimeout(this.retryTimer), null);
2752
+ }
2753
+ calculateRetryDelay() {
2754
+ let e = Xn * Zn ** +Math.min(this.retryCount, 2);
2755
+ return Math.min(e, Yn);
2756
+ }
2757
+ startPingTimer() {
2758
+ this.pingTimer = setInterval(() => {
2759
+ if (!this.ws || this.ws.readyState !== S.OPEN) {
2760
+ this.stopPingTimer();
2761
+ return;
2762
+ }
2763
+ this.ws.ping(), D().debug?.("[claw-cloud-socket] sent ping to server");
2764
+ let { deviceInfo: e } = this.options, t = {
2765
+ msgType: "pingMessage",
2766
+ sourceRole: "yoyoclaw",
2767
+ sourceDeviceId: e.deviceId,
2768
+ targetRole: "node",
2769
+ port: e.port
2770
+ };
2771
+ try {
2772
+ this.ws.send(JSON.stringify(t)), D().debug?.("[claw-cloud-socket] sent pingMessage to server");
2773
+ } catch {
2774
+ D().error("[claw-cloud-socket] failed to send pingMessage");
2775
+ }
2776
+ }, Jn);
2777
+ }
2778
+ stopPingTimer() {
2779
+ this.pingTimer &&= (clearInterval(this.pingTimer), null);
2780
+ }
2781
+ pauseRetry() {
2782
+ this.isRetryPaused || (this.isRetryPaused = !0, this.clearRetryTimer(), D().info("[claw-cloud-socket] retry paused"));
2783
+ }
2784
+ resumeRetry() {
2785
+ this.isRetryPaused && (this.isRetryPaused = !1, D().info("[claw-cloud-socket] retry resumed"), (!this.ws || this.ws.readyState !== S.OPEN) && (this.retryCount = 0, this.connect(!0)));
2786
+ }
2787
+ }, er = ".openclaw/yoyo/tools", tr = /[<>:"/\\|?*]/;
2788
+ async function nr(e, t) {
2789
+ let n = 0, r = 0;
2790
+ for (let i of t) {
2791
+ let t = rr(i.name);
2792
+ if (!t) {
2793
+ r += 1;
2794
+ continue;
2795
+ }
2796
+ await B({
2797
+ rootDir: e,
2798
+ relativePath: u.join(er, t),
2799
+ data: JSON.stringify(i, null, 2),
2800
+ encoding: "utf8",
2801
+ mkdir: !0
2802
+ }), n += 1;
2803
+ }
2804
+ return {
2805
+ archiveDir: u.join(e, ".openclaw", "yoyo", "tools"),
2806
+ writtenCount: n,
2807
+ skippedCount: r
2808
+ };
2809
+ }
2810
+ function rr(e) {
2811
+ let t = e.trim();
2812
+ if (!(!t || tr.test(t) || ir(t))) return `${t}.json`;
2813
+ }
2814
+ function ir(e) {
2815
+ for (let t of e) if (t.codePointAt(0) < 32) return !0;
2816
+ return !1;
2817
+ }
2818
+ //#endregion
2819
+ //#region src/modules/device-toolset/copy-fallback.ts
2820
+ var ar = ".yoyo-device-toolset-copy-fallback";
2821
+ async function or(e, t) {
2822
+ await cr(t), await v.rm(t, {
2823
+ recursive: !0,
2824
+ force: !0
2825
+ }), await v.mkdir(t, { recursive: !0 }), await lr(e, t), await v.writeFile(u.join(t, ar), "Managed copy fallback for DeviceToolSet MCP tools.\n", "utf8");
2826
+ }
2827
+ async function sr(e) {
2828
+ try {
2829
+ return (await v.stat(u.join(e, ar))).isFile();
2830
+ } catch {
2831
+ return !1;
2832
+ }
2833
+ }
2834
+ async function cr(e) {
2835
+ let t;
2836
+ try {
2837
+ t = await v.lstat(e);
2838
+ } catch (e) {
2839
+ if (ur(e)) return;
2840
+ throw e;
2841
+ }
2842
+ if (!t.isSymbolicLink()) {
2843
+ if (!t.isDirectory()) throw Error(`Cannot replace unmanaged mcptools path: ${e}`);
2844
+ if (!((await v.readdir(e)).length === 0 || await sr(e))) throw Error(`Cannot replace unmanaged mcptools directory: ${e}`);
2845
+ }
2846
+ }
2847
+ async function lr(e, t) {
2848
+ let n = await v.readdir(e, { withFileTypes: !0 });
2849
+ for (let r of n) {
2850
+ let n = u.join(e, r.name), i = u.join(t, r.name);
2851
+ r.isDirectory() ? (await v.mkdir(i, { recursive: !0 }), await lr(n, i)) : r.isFile() && await v.copyFile(n, i);
2852
+ }
2853
+ }
2854
+ function ur(e) {
2855
+ return !!(e && typeof e == "object" && "code" in e && e.code === "ENOENT");
2856
+ }
2857
+ //#endregion
2858
+ //#region src/modules/device-toolset/link.ts
2859
+ async function dr(e, t, n = {}) {
2860
+ await v.mkdir(e, { recursive: !0 });
2861
+ let r = await v.realpath(e), i = await fr(t);
2862
+ if (i.exists) {
2863
+ if (i.isLink) {
2864
+ if (await pr(t, r)) return { mode: "already-linked" };
2865
+ throw Error(`Cannot replace unmanaged mcptools link: ${t}`);
2866
+ }
2867
+ if (!await mr(t, i.isDirectory)) throw Error(`Cannot replace unmanaged mcptools directory: ${t}`);
2868
+ await v.rm(t, {
2869
+ recursive: !0,
2870
+ force: !0
2871
+ });
2872
+ }
2873
+ await v.mkdir(u.dirname(t), { recursive: !0 });
2874
+ try {
2875
+ return await (n.symlink ?? v.symlink)(r, t, process.platform === "win32" ? "junction" : "dir"), { mode: "linked" };
2876
+ } catch {
2877
+ return await (n.copyFallback ?? or)(r, t), { mode: "copy-fallback" };
2878
+ }
2879
+ }
2880
+ async function fr(e) {
2881
+ try {
2882
+ let t = await v.lstat(e);
2883
+ return {
2884
+ exists: !0,
2885
+ isLink: t.isSymbolicLink(),
2886
+ isDirectory: t.isDirectory()
2887
+ };
2888
+ } catch (e) {
2889
+ if (gr(e)) return {
2890
+ exists: !1,
2891
+ isLink: !1,
2892
+ isDirectory: !1
2893
+ };
2894
+ throw e;
2895
+ }
2896
+ }
2897
+ async function pr(e, t) {
2898
+ try {
2899
+ return hr(await v.realpath(e), t);
2900
+ } catch {
2901
+ return !1;
2902
+ }
2903
+ }
2904
+ async function mr(e, t) {
2905
+ return t ? (await v.readdir(e)).length === 0 || await sr(e) : !1;
2906
+ }
2907
+ function hr(e, t) {
2908
+ return process.platform === "win32" ? e.toLowerCase() === t.toLowerCase() : e === t;
2909
+ }
2910
+ function gr(e) {
2911
+ return !!(e && typeof e == "object" && "code" in e && e.code === "ENOENT");
2912
+ }
2913
+ //#endregion
2914
+ //#region src/modules/device-toolset/md5-index.ts
2915
+ var _r = ".openclaw/yoyo/toolset-md5.json", vr = 1024 * 1024;
2916
+ function yr() {
2917
+ return {
2918
+ version: 1,
2919
+ nodes: {}
2920
+ };
2921
+ }
2922
+ function br(e) {
2923
+ return JSON.stringify(Tr(e));
2924
+ }
2925
+ function xr(e) {
2926
+ return ae("md5").update(br(e)).digest("hex");
2927
+ }
2928
+ async function Sr(e) {
2929
+ try {
2930
+ let t = await xt({
2931
+ rootDir: e,
2932
+ relativePath: _r,
2933
+ maxBytes: vr
2934
+ }), n = JSON.parse(t.buffer.toString("utf8"));
2935
+ return {
2936
+ version: 1,
2937
+ nodes: n && typeof n.nodes == "object" && n.nodes ? n.nodes : {}
2938
+ };
2939
+ } catch (e) {
2940
+ if (e instanceof I && e.code === "not-found") return yr();
2941
+ throw e;
2942
+ }
2943
+ }
2944
+ async function Cr(e, t, n) {
2945
+ let r = (await Sr(e)).nodes[t]?.md5;
2946
+ return {
2947
+ changed: r !== n,
2948
+ md5: n,
2949
+ previousMd5: r
2950
+ };
2951
+ }
2952
+ async function wr(e, t, n, r = Date.now()) {
2953
+ let i = {
2954
+ version: 1,
2955
+ nodes: {
2956
+ ...(await Sr(e)).nodes,
2957
+ [t]: {
2958
+ md5: n,
2959
+ updatedAtMs: r
2960
+ }
2961
+ }
2962
+ };
2963
+ return await B({
2964
+ rootDir: e,
2965
+ relativePath: _r,
2966
+ data: JSON.stringify(i, null, 2),
2967
+ encoding: "utf8",
2968
+ mkdir: !0
2969
+ }), i;
2970
+ }
2971
+ function Tr(e) {
2972
+ if (Array.isArray(e)) return e.map(Tr);
2973
+ if (!e || typeof e != "object") return e;
2974
+ let t = {};
2975
+ for (let n of Object.keys(e).toSorted()) {
2976
+ let r = e[n];
2977
+ r !== void 0 && (t[n] = Tr(r));
2978
+ }
2979
+ return t;
2980
+ }
2981
+ //#endregion
2982
+ //#region src/modules/device-toolset/normalize.ts
2983
+ function Y(e) {
2984
+ return typeof e == "string" && e.trim() ? e : void 0;
2985
+ }
2986
+ function Er(e) {
2987
+ if (!e || typeof e != "object") throw Error("DeviceToolSet payload must be an object");
2988
+ let t = e;
2989
+ if (!Y(t.nodeId)) throw Error("DeviceToolSet payload missing nodeId");
2990
+ if (!Array.isArray(t.toolSet)) throw Error("DeviceToolSet payload toolSet must be an array");
2991
+ return e;
2992
+ }
2993
+ function Dr(e) {
2994
+ let t = e.nodeId, n = [], r = 0;
2995
+ for (let t of e.toolSet) {
2996
+ let e = Or(t);
2997
+ e ? n.push(e) : r += 1;
2998
+ }
2999
+ return {
3000
+ nodeId: t,
3001
+ tools: n,
3002
+ skippedCount: r
3003
+ };
3004
+ }
3005
+ function Or(e) {
3006
+ let t = Y(e.tool?.id), n = Y(e.tool?.function?.name), r = Y(e.tool?.function?.description);
3007
+ if (!t || e.tool?.type !== "function" || !n || !r) return;
3008
+ let i = {
3009
+ id: t,
3010
+ type: "function",
3011
+ name: n,
3012
+ description: r
3013
+ };
3014
+ e.tool.function?.inputSchema && (i.inputSchema = e.tool.function.inputSchema), e.tool.function?.outputSchema && (i.outputSchema = e.tool.function.outputSchema), e.tool.function?.examples && (i.examples = e.tool.function.examples);
3015
+ let a = Y(e.executeParams?.pkgName);
3016
+ return a && (i.pkgName = a), i;
3017
+ }
3018
+ //#endregion
3019
+ //#region src/modules/device-toolset/persist.ts
3020
+ var kr = ".openclaw/yoyo/device-toolsets.json", Ar = 10 * 1024 * 1024;
3021
+ function jr() {
3022
+ return {
3023
+ version: 1,
3024
+ tools: {}
3025
+ };
3026
+ }
3027
+ async function Mr(e) {
3028
+ try {
3029
+ let t = await xt({
3030
+ rootDir: e,
3031
+ relativePath: kr,
3032
+ maxBytes: Ar
3033
+ }), n = JSON.parse(t.buffer.toString("utf8"));
3034
+ return {
3035
+ version: 1,
3036
+ tools: n && typeof n.tools == "object" && n.tools ? n.tools : {}
3037
+ };
3038
+ } catch (e) {
3039
+ if (e instanceof I && e.code === "not-found") return jr();
3040
+ throw e;
3041
+ }
3042
+ }
3043
+ async function Nr(e, t, n) {
3044
+ let r = {
3045
+ version: 1,
3046
+ tools: Pr((await Mr(e)).tools, t, n)
3047
+ };
3048
+ return await B({
3049
+ rootDir: e,
3050
+ relativePath: kr,
3051
+ data: JSON.stringify(r, null, 2),
3052
+ encoding: "utf8",
3053
+ mkdir: !0
3054
+ }), {
3055
+ changed: !0,
3056
+ nodeCount: Ir(r.tools),
3057
+ toolCount: Object.keys(r.tools).length,
3058
+ cache: r
3059
+ };
3060
+ }
3061
+ function Pr(e, t, n) {
3062
+ let r = { ...e };
3063
+ for (let e of n) {
3064
+ let n = r[e.id];
3065
+ r[e.id] = {
3066
+ id: e.id,
3067
+ name: e.name,
3068
+ description: e.description,
3069
+ supportedNodeIds: Fr(n?.supportedNodeIds ?? [], t)
3070
+ };
3071
+ }
3072
+ return r;
3073
+ }
3074
+ function Fr(e, t) {
3075
+ return [...new Set([...e, t])];
3076
+ }
3077
+ function Ir(e) {
3078
+ let t = /* @__PURE__ */ new Set();
3079
+ for (let n of Object.values(e)) for (let e of n.supportedNodeIds) t.add(e);
3080
+ return t.size;
3081
+ }
3082
+ //#endregion
3083
+ //#region src/modules/device-toolset/skill-inject.ts
3084
+ var Lr = u.join("skills", "yoyo-control", "SKILL.md"), Rr = u.join("skills", "yoyo-control", "configs", "sub-skills.json"), zr = "{{full-mcp-tool-list}}", Br = "<!-- yoyo-mcp-tools:start -->", Vr = "<!-- yoyo-mcp-tools:end -->";
3085
+ async function Hr(e, t) {
3086
+ let n = u.join(e, Lr), r = await v.readFile(n, "utf8"), i = Wr(t, await Ur(e)), a = Kr(r, Gr(i));
3087
+ return a !== r && await v.writeFile(n, a, "utf8"), {
3088
+ skillPath: n,
3089
+ rowCount: Object.keys(i).length
3090
+ };
3091
+ }
3092
+ async function Ur(e) {
3093
+ let t = u.join(e, Rr), n;
3094
+ try {
3095
+ n = await v.readFile(t, "utf8");
3096
+ } catch (e) {
3097
+ if (Yr(e) && e.code === "ENOENT") return /* @__PURE__ */ new Set();
3098
+ throw e;
3099
+ }
3100
+ let r = JSON.parse(n);
3101
+ if (!Array.isArray(r) || r.some((e) => typeof e != "string")) throw Error("sub-skills config must be a JSON array of tool names");
3102
+ return new Set(r.map((e) => e.trim()).filter(Boolean));
3103
+ }
3104
+ function Wr(e, t) {
3105
+ return t.size === 0 ? e : Object.fromEntries(Object.entries(e).filter(([e, n]) => !t.has(e) && !t.has(n.name)));
3106
+ }
3107
+ function Gr(e) {
3108
+ return [
3109
+ Br,
3110
+ ...Object.values(e).toSorted((e, t) => e.name.localeCompare(t.name)).map((e) => `| ${qr(e.name)} | ${qr(e.description)} | ${qr(e.supportedNodeIds.join(", "))} |`),
3111
+ Vr
3112
+ ].join("\n");
3113
+ }
3114
+ function Kr(e, t) {
3115
+ let n = RegExp(`${Jr(Br)}[\\s\\S]*?${Jr(Vr)}`);
3116
+ if (n.test(e)) return e.replace(n, t);
3117
+ if (e.includes(zr)) return e.replace(zr, t);
3118
+ throw Error("Unable to find MCP tools placeholder or generated block in yoyo-control skill");
3119
+ }
3120
+ function qr(e) {
3121
+ return e.replaceAll("|", "\\|").replace(/\r?\n/g, " ");
3122
+ }
3123
+ function Jr(e) {
3124
+ return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3125
+ }
3126
+ function Yr(e) {
3127
+ return e instanceof Error && "code" in e;
3128
+ }
3129
+ //#endregion
3130
+ //#region src/modules/device-toolset/processor.ts
3131
+ var Xr = Dt();
3132
+ async function Zr(e) {
3133
+ let t = Er(e), n = Ot();
3134
+ if (!n) throw Error("Unable to resolve home directory for DeviceToolSet persistence");
3135
+ let r = Dr(t);
3136
+ D().info(`[yoyoclaw-device-toolset] process start, nodeId: ${r.nodeId}, tools: ${r.tools.length}, skipped: ${r.skippedCount}`);
3137
+ let i = xr(r.tools);
3138
+ if (D().debug?.(`[yoyoclaw-device-toolset] computed md5, nodeId: ${r.nodeId}, md5: ${i}`), !(await Cr(n, r.nodeId, i)).changed) return D().info(`[yoyoclaw-device-toolset] unchanged, skip refresh, nodeId: ${r.nodeId}`), {
3139
+ changed: !1,
3140
+ nodeId: r.nodeId,
3141
+ skippedCount: r.skippedCount
3142
+ };
3143
+ let a = await Nr(n, r.nodeId, r.tools);
3144
+ D().info(`[yoyoclaw-device-toolset] cache merged, nodeId: ${r.nodeId}, supportedNodes: ${a.nodeCount}, tools: ${a.toolCount}`);
3145
+ let o = a.cache.tools, s = await nr(n, r.tools);
3146
+ D().info(`[yoyoclaw-device-toolset] archive refreshed, nodeId: ${r.nodeId}, written: ${s.writtenCount}, skipped: ${s.skippedCount}`);
3147
+ let c = await Hr(Xr, o);
3148
+ D().info(`[yoyoclaw-device-toolset] skill refreshed, nodeId: ${r.nodeId}, rows: ${c.rowCount}`);
3149
+ let l = await dr(s.archiveDir, u.join(Xr, "skills", "yoyo-control", "mcptools"));
3150
+ return D().info(`[yoyoclaw-device-toolset] mapping ready, nodeId: ${r.nodeId}, mode: ${l.mode}`), await wr(n, r.nodeId, i, Date.now()), D().info(`[yoyoclaw-device-toolset] process complete, nodeId: ${r.nodeId}`), {
3151
+ changed: !0,
3152
+ nodeId: r.nodeId,
3153
+ nodeCount: a.nodeCount,
3154
+ toolCount: a.toolCount,
3155
+ skippedCount: r.skippedCount
3156
+ };
3157
+ }
3158
+ //#endregion
3159
+ //#region src/cloud-channel/message-handler.ts
3160
+ var Qr = { style: "SOUL.md" }, X = "[yoyoclaw-channel]", $r = class {
3161
+ sessionManager;
3162
+ adminClientManager;
3163
+ config;
3164
+ pendingFirstMessages = /* @__PURE__ */ new Map();
3165
+ initializedDeviceIds = /* @__PURE__ */ new Set();
3166
+ contextUpdateHandlers = {
3167
+ style: this.updateStyleContext.bind(this),
3168
+ "model.primary": this.updatePrimaryModel.bind(this),
3169
+ DeviceToolSet: this.updateDeviceToolSetContext.bind(this),
3170
+ UniversalToolSet: this.updateDeviceToolSetContext.bind(this)
3171
+ };
3172
+ contextFetchHandlers = {
3173
+ skills: this.fetchSkillsStatus.bind(this),
3174
+ "models.list": this.fetchModelsList.bind(this)
3175
+ };
3176
+ constructor(e) {
3177
+ this.sessionManager = e.sessionManager, this.adminClientManager = e.adminClientManager, this.config = e.config;
3178
+ }
3179
+ handleCloudMessage = (e) => {
3180
+ switch (e.msgType) {
3181
+ case "devicePairMessage":
3182
+ this.handlePairMessage(e);
3183
+ break;
3184
+ case "deviceUnPairMessage":
3185
+ this.handleUnPairMessage(e);
3186
+ break;
3187
+ case "userMessage":
3188
+ this.handleUserMessage(e);
3189
+ break;
3190
+ case "updateContexts":
3191
+ case "fetchContexts":
3192
+ this.handleContextRequest(e);
3193
+ break;
3194
+ }
3195
+ };
3196
+ handlePairMessage(e) {
3197
+ let { sourceDeviceId: t, sourceDeviceInfo: n, targetDeviceId: r, port: i, sessionInfo: a, traceInfo: o } = e;
3198
+ if (!t || !r || !i || !n?.deviceId) return;
3199
+ let s = n.deviceId, c = a?.nodeConnectTimestamp;
3200
+ c ? (this.sessionManager.closePreviousNodeGatewayClients(s, c), this.flushPendingMessage(s), this.initializedDeviceIds.delete(s)) : D().warn(`${X} pair message missing timestamp for device: ${t}`), D().info(`${X} received pair message, creating gateway client for device: ${t}, hardware device: ${s}, timestamp: ${c}`);
3201
+ let l = {
3202
+ sessionId: t,
3203
+ timestamp: c || 0,
3204
+ sourceInfo: {
3205
+ sourceRole: n?.role ?? "node",
3206
+ sourceDeviceId: t,
3207
+ sourceDeviceInfo: n
3208
+ }
3209
+ };
3210
+ this.sessionManager.addSession(s, l), this.config.onStatusEvent?.({
3211
+ type: G.DEVICE_PAIRING,
3212
+ timestamp: Date.now(),
3213
+ data: {
3214
+ sessionId: t,
3215
+ hardwareDeviceId: s,
3216
+ deviceInfo: n,
3217
+ pairedAt: (/* @__PURE__ */ new Date()).toISOString()
3218
+ }
3219
+ }), this.sessionManager.createNodeGatewayClient({
3220
+ sessionId: t,
3221
+ hardwareDeviceId: s,
3222
+ deviceInfo: n,
3223
+ onMessage: (e) => this.handleNodeGatewayMessage(t, o, e),
3224
+ onStatusEvent: (e) => {
3225
+ this.config.onStatusEvent?.(e);
3226
+ }
3227
+ }).connect();
3228
+ }
3229
+ handleUnPairMessage(e) {
3230
+ let { sourceDeviceId: t } = e;
3231
+ if (!t) {
3232
+ D().warn(`${X} unpair message missing sourceDeviceId`);
3233
+ return;
3234
+ }
3235
+ let n = this.sessionManager.getHardwareDeviceId(t);
3236
+ D().info(`${X} received unpair message, session: ${t}, hardware device: ${n}`), this.config.onStatusEvent?.({
3237
+ type: G.DEVICE_UNPAIRING,
3238
+ timestamp: Date.now(),
3239
+ data: {
3240
+ sessionId: t,
3241
+ hardwareDeviceId: n ?? "",
3242
+ reason: "remote device offline",
3243
+ unpairedAt: (/* @__PURE__ */ new Date()).toISOString()
3244
+ }
3245
+ }), this.sessionManager.closeNodeGatewayClient(t), n && (this.flushPendingMessage(n), this.initializedDeviceIds.delete(n));
3246
+ }
3247
+ handleUserMessage(e) {
3248
+ let { sourceDeviceId: t } = e || {};
3249
+ if (!t) {
3250
+ D().warn(`${X} user message missing sourceDeviceId`);
3251
+ return;
3252
+ }
3253
+ let n = this.sessionManager.getHardwareDeviceId(t);
3254
+ if (!n) {
3255
+ D().warn(`${X} user message missing hardwareDeviceId, session: ${t}`);
3256
+ return;
3257
+ }
3258
+ try {
3259
+ let r = this.sessionManager.getNodeGatewayClient(t);
3260
+ if (!r) {
3261
+ D().warn(`${X} no node gateway client found for source device: ${n}, session: ${t}`);
3262
+ return;
3263
+ }
3264
+ e.data && (this.initializedDeviceIds.has(n) || this.processMessageBuffer(t, n, e.data, r)) && this.forwardToNodeGateway(t, n, r, e.data);
3265
+ } catch (e) {
3266
+ D().error(`${X} failed to send gateway message to device: ${n}, session: ${t}, ${String(e)}`);
3267
+ }
3268
+ }
3269
+ forwardToNodeGateway(e, t, n, r) {
3270
+ D().info(`${X} forwarding user message to node gateway from ${t}, session: ${e}`), n.send(r);
3271
+ }
3272
+ processMessageBuffer(e, t, n, r) {
3273
+ let i = this.pendingFirstMessages.get(t);
3274
+ if (!i) {
3275
+ let r = setTimeout(() => this.flushPendingMessage(t), 500);
3276
+ return this.pendingFirstMessages.set(t, {
3277
+ sessionId: e,
3278
+ data: n,
3279
+ timeout: r
3280
+ }), !1;
3281
+ }
3282
+ return i.sessionId === e ? !0 : (this.flushPendingMessage(t, {
3283
+ sessionId: e,
3284
+ data: n,
3285
+ client: r
3286
+ }), !1);
3287
+ }
3288
+ flushPendingMessage(e, t) {
3289
+ let n = this.pendingFirstMessages.get(e);
3290
+ if (!n) return;
3291
+ clearTimeout(n.timeout), this.pendingFirstMessages.delete(e), this.initializedDeviceIds.add(e);
3292
+ let r = this.sessionManager.getNodeGatewayClient(n.sessionId);
3293
+ r && this.forwardToNodeGateway(n.sessionId, e, r, n.data), t && this.forwardToNodeGateway(t.sessionId, e, t.client, t.data);
3294
+ }
3295
+ handleNodeGatewayMessage = async (e, t, n) => {
3296
+ let r = this.sessionManager.getHardwareDeviceId(e), i = this.sessionManager.getSession(e), a = i?.sourceInfo.sourceDeviceInfo?.deviceId;
3297
+ if (!r || !i) {
3298
+ D().warn(`${X} gateway source offline, session: ${e}`);
3299
+ return;
3300
+ }
3301
+ D().info(`${X} received gateway message from ${a}`);
3302
+ try {
3303
+ let e = i.sourceInfo.sourceDeviceId, r;
3304
+ try {
3305
+ r = JSON.parse(n);
3306
+ } catch {
3307
+ D().warn(`${X} gateway message is not valid JSON`);
3308
+ return;
3309
+ }
3310
+ if (!r.ok && r.error?.code === "NOT_PAIRED") {
3311
+ let n = r.error?.details?.requestId;
3312
+ if (!n) {
3313
+ D().warn(`${X} NOT_PAIRED without requestId, ignoring...`);
3314
+ return;
3315
+ }
3316
+ await this.handleAutoPair(n);
3317
+ let i = {
3318
+ id: r.id,
3319
+ type: "reconnect-required"
3320
+ };
3321
+ this.sendMessage("deviceControl", e, t, "", void 0, i), D().info(`${X} auto pair is completed, requestId: ${n}`);
3322
+ return;
3323
+ }
3324
+ D().debug?.(`${X} trans gateway msg to cloud, session: ${e}, data: ${n.slice(0, 1e3)}`), this.sendMessage("userMessage", e, t, n) || (D().error(`${X} failed to send message, cloud socket closed, session ${e}, device ${a}`), this.sessionManager.closeNodeGatewayClient(e));
3325
+ } catch (e) {
3326
+ D().error(`${X} failed to handle gateway message: ${String(e)}`);
3327
+ }
3328
+ };
3329
+ async handleAutoPair(e) {
3330
+ let t = this.adminClientManager.getClient();
3331
+ if (!t) return D().warn(`${X} admin client not available for auto pair`), !1;
3332
+ try {
3333
+ D().info(`${X} auto pair approve, requestId: ${e}`), await t.devicePairApprove(e);
3334
+ } catch (t) {
3335
+ D().error(`${X} auto pair approve failed, requestId: ${e}, error: ${String(t)}, ignore...`);
3336
+ }
3337
+ }
3338
+ async handleContextRequest(e) {
3339
+ let { sourceDeviceId: t, traceInfo: n } = e, r = e.msgType, i = r === "updateContexts";
3340
+ if (!t) {
3341
+ D().warn(`${X} context request missing sourceDeviceId`);
3342
+ return;
3343
+ }
3344
+ D().info(`${X} handling ${r} from ${t} traceInfo: ${JSON.stringify(n)}`);
3345
+ let a = e.contexts?.[0], o = this.validateContext(a);
3346
+ if (!o.valid) {
3347
+ this.replyContextError(r, t, n, a, o.error);
3348
+ return;
3349
+ }
3350
+ let s = o.context, c = s.header.name;
3351
+ try {
3352
+ let e = i ? this.contextUpdateHandlers[c] : this.contextFetchHandlers[c];
3353
+ if (!e) {
3354
+ this.replyContextError(r, t, n, a, `Unsupported context name: ${c}`);
3355
+ return;
3356
+ }
3357
+ if (this.contextHandlerRequiresAdminClient(i, c) && !await this.ensureAdminClientReady(r, t, n, s)) return;
3358
+ let o = this.adminClientManager.getClient(), l = i ? await e(o ?? void 0, s.payload, s) : await e(o);
3359
+ if (l.noReply) {
3360
+ D().info(`${X} ${i ? "update" : "fetch"} context '${c}' processed (no reply)`);
3361
+ return;
3362
+ }
3363
+ l.ok ? (D().info(`${X} ${i ? "update" : "fetch"} context successfully`), this.sendContextResponse(r, t, n, a, {
3364
+ ok: !0,
3365
+ ...l.data
3366
+ })) : (D().error(`${X} failed to ${i ? "update" : "fetch"} context: ${l.error}`), this.sendContextResponse(r, t, n, a, {
3367
+ ok: !1,
3368
+ error: l.error,
3369
+ ...l?.data,
3370
+ ...i && { name: c }
3371
+ }));
3372
+ } catch (e) {
3373
+ let o = e instanceof Error ? e.message : String(e);
3374
+ D().error(`${X} error ${i ? "updating" : "fetching"} context '${c}': ${o}`), this.replyContextError(r, t, n, a, o);
3375
+ }
3376
+ }
3377
+ sendMessage(e, t, n, r, i, a) {
3378
+ let o = {
3379
+ msgType: e,
3380
+ sourceRole: "yoyoclaw",
3381
+ sourceDeviceId: this.config.deviceInfo.deviceId,
3382
+ traceInfo: n,
3383
+ targetRole: "node",
3384
+ targetDeviceId: t,
3385
+ port: this.config.deviceInfo.port,
3386
+ data: typeof r == "string" ? r : JSON.stringify(r),
3387
+ contexts: i,
3388
+ bizExtInfo: a
3389
+ };
3390
+ return this.config.onReply(o, t);
3391
+ }
3392
+ validateContext(e) {
3393
+ return e?.header?.name ? {
3394
+ valid: !0,
3395
+ context: e
3396
+ } : {
3397
+ valid: !1,
3398
+ error: "Missing context name"
3399
+ };
3400
+ }
3401
+ buildResponseContext(e, t) {
3402
+ return [{
3403
+ header: e ? e.header : {
3404
+ name: "unknown",
3405
+ namespace: "yoyoclaw"
3406
+ },
3407
+ payload: t
3408
+ }];
3409
+ }
3410
+ replyContextError(e, t, n, r, i) {
3411
+ D().error(`${X} ${i}`), this.sendContextResponse(e, t, n, r, {
3412
+ ok: !1,
3413
+ error: i
3414
+ });
3415
+ }
3416
+ sendContextResponse(e, t, n, r, i) {
3417
+ let a = this.buildResponseContext(r, i);
3418
+ if (r?.header.name === "style" && e === "updateContexts") {
3419
+ this.sendMessage(e, t, n, JSON.stringify({ success: !0 }), a);
3420
+ return;
3421
+ }
3422
+ this.sendMessage(e, t, n, "", a);
3423
+ }
3424
+ async ensureAdminClientReady(e, t, n, r) {
3425
+ return await this.adminClientManager.waitForReady() ? !0 : (this.replyContextError(e, t, n, r, "Admin gateway client not ready"), !1);
3426
+ }
3427
+ async updateStyleContext(e, t) {
3428
+ if (!e) return {
3429
+ ok: !1,
3430
+ error: "Admin gateway client not ready"
3431
+ };
3432
+ let { content: n } = t || {};
3433
+ if (!n) return {
3434
+ ok: !1,
3435
+ error: "Missing content in context payload"
3436
+ };
3437
+ let r = Qr.style, i = await e.setAgentFile(r, n);
3438
+ return i.ok ? {
3439
+ ok: !0,
3440
+ data: { name: "style" }
3441
+ } : {
3442
+ ok: !1,
3443
+ error: `update context failed, ${JSON.stringify(i.error)}`
3444
+ };
3445
+ }
3446
+ async updatePrimaryModel(e, t) {
3447
+ if (!e) return {
3448
+ ok: !1,
3449
+ error: "Admin gateway client not ready"
3450
+ };
3451
+ let { provider: n, id: r } = t;
3452
+ if (!n || !r) return {
3453
+ ok: !1,
3454
+ error: "Missing provider or id in context payload"
3455
+ };
3456
+ try {
3457
+ return (await e.switchPrimaryModel(n, r)).ok ? (D().info(`[yoyoclaw-channel] switchPrimaryModel success: ${n}/${r}`), {
3458
+ ok: !0,
3459
+ data: { resolved: {
3460
+ provider: n,
3461
+ id: r
3462
+ } }
3463
+ }) : (D().error("[yoyoclaw-channel] switchPrimaryModel failed, try to fallback main session model"), this.getMainSessionModel(e));
3464
+ } catch (t) {
3465
+ return D().error(`[yoyoclaw-channel] updatePrimaryModel error: ${t}, try to fallback main session model`), this.getMainSessionModel(e);
3466
+ }
3467
+ }
3468
+ async getMainSessionModel(e) {
3469
+ try {
3470
+ let t = await e.getMainSession(), { modelProvider: n = "", model: r = "" } = t;
3471
+ return D().warn(`[yoyoclaw-channel] switchPrimaryModel failed, fallback to current: ${n}/${r}`), !n || !r ? {
3472
+ ok: !1,
3473
+ error: `Missing primary model: mainSession-${JSON.stringify(t)}`
3474
+ } : {
3475
+ ok: !1,
3476
+ data: { resolved: {
3477
+ provider: n,
3478
+ id: r
3479
+ } }
3480
+ };
3481
+ } catch (e) {
3482
+ return {
3483
+ ok: !1,
3484
+ error: `getMainSessionModel error: ${e instanceof Error ? e.message : String(e)}`
3485
+ };
3486
+ }
3487
+ }
3488
+ async fetchSkillsStatus(e) {
3489
+ return {
3490
+ ok: !0,
3491
+ data: { skills: (await e.getSkillsStatus()).skills?.filter((e) => e.eligible).map((e) => ({
3492
+ name: e.name,
3493
+ description: e.description,
3494
+ source: e.source,
3495
+ disableModelInvocation: e.disabled
3496
+ })) ?? [] }
3497
+ };
3498
+ }
3499
+ async fetchModelsList(e) {
3500
+ try {
3501
+ let t = await e.getModelList(), { modelProvider: n = "", model: r = "" } = await e.getMainSession();
3502
+ return D().info(`[yoyoclaw-channel] current primary model: ${n}/${r}`), {
3503
+ ok: !0,
3504
+ data: { models: t?.models?.map((e) => {
3505
+ let t = e.provider === n && e.id === r;
3506
+ return {
3507
+ ...e,
3508
+ primary: t
3509
+ };
3510
+ }) ?? [] }
3511
+ };
3512
+ } catch (e) {
3513
+ let t = e instanceof Error ? e.message : String(e);
3514
+ return D().error(`[yoyoclaw-channel] fetchModelsList failed: ${t}`), {
3515
+ ok: !1,
3516
+ error: `fetchModelsList error: ${t}`
3517
+ };
3518
+ }
3519
+ }
3520
+ contextHandlerRequiresAdminClient(e, t) {
3521
+ return !e || t !== "DeviceToolSet" && t !== "UniversalToolSet";
3522
+ }
3523
+ async updateDeviceToolSetContext(e, t, n) {
3524
+ return n?.header.namespace === "yoyoclaw" ? {
3525
+ ok: !0,
3526
+ data: await Zr(t),
3527
+ noReply: !0
3528
+ } : {
3529
+ ok: !1,
3530
+ error: `Unsupported DeviceToolSet namespace: ${n?.header.namespace ?? "unknown"}`
3531
+ };
3532
+ }
3533
+ }, ei = class extends jn {
3534
+ nodeOpts;
3535
+ sessionId;
3536
+ hardwareDeviceId;
3537
+ deviceInfo;
3538
+ connectedAt;
3539
+ constructor(e) {
3540
+ super(e), this.nodeOpts = e, this.sessionId = e.sessionId, this.hardwareDeviceId = e.hardwareDeviceId, this.deviceInfo = e.deviceInfo;
3541
+ }
3542
+ getSessionId() {
3543
+ return this.sessionId;
3544
+ }
3545
+ getHardwareDeviceId() {
3546
+ return this.hardwareDeviceId;
3547
+ }
3548
+ onOpen() {
3549
+ this.connectedAt = (/* @__PURE__ */ new Date()).toISOString(), D().info(`[yoyoclaw-nodeGatewayClient] connected for session: ${this.sessionId}, device: ${this.hardwareDeviceId}`), this.nodeOpts.onStatusEvent?.({
3550
+ type: G.GATEWAY_CLIENT_CONNECTED,
3551
+ timestamp: Date.now(),
3552
+ data: {
3553
+ sessionId: this.sessionId,
3554
+ hardwareDeviceId: this.hardwareDeviceId,
3555
+ deviceInfo: this.deviceInfo,
3556
+ connectedAt: this.connectedAt
3557
+ }
3558
+ });
3559
+ }
3560
+ onClose(e, t) {
3561
+ D().info(`[yoyoclaw-nodeGatewayClient] disconnected for session: ${this.sessionId}, device: ${this.hardwareDeviceId}, reason: ${t}`), this.nodeOpts.onStatusEvent?.({
3562
+ type: G.GATEWAY_CLIENT_DISCONNECTED,
3563
+ timestamp: Date.now(),
3564
+ data: {
3565
+ sessionId: this.sessionId,
3566
+ hardwareDeviceId: this.hardwareDeviceId,
3567
+ disconnectedAt: (/* @__PURE__ */ new Date()).toISOString(),
3568
+ reason: t
3569
+ }
3570
+ });
3571
+ }
3572
+ onError(e) {
3573
+ D().error(`[yoyoclaw-nodeGatewayClient] error for session: ${this.sessionId}, device: ${this.hardwareDeviceId}: ${e.message}`);
3574
+ }
3575
+ }, ti = class {
3576
+ nodeGatewayClientsMap = /* @__PURE__ */ new Map();
3577
+ deviceSessionsMap = /* @__PURE__ */ new Map();
3578
+ sessionIdToHardwareDeviceMap = /* @__PURE__ */ new Map();
3579
+ addSession(e, t) {
3580
+ let n = this.deviceSessionsMap.get(e) || [];
3581
+ n.push(t), this.deviceSessionsMap.set(e, n);
3582
+ }
3583
+ removeSession(e) {
3584
+ let t = this.sessionIdToHardwareDeviceMap.get(e);
3585
+ if (t) {
3586
+ let n = this.deviceSessionsMap.get(t);
3587
+ if (n) {
3588
+ let r = n.findIndex((t) => t.sessionId === e);
3589
+ r !== -1 && n.splice(r, 1), n.length === 0 && this.deviceSessionsMap.delete(t);
3590
+ }
3591
+ this.sessionIdToHardwareDeviceMap.delete(e);
3592
+ }
3593
+ }
3594
+ getSession(e) {
3595
+ let t = this.sessionIdToHardwareDeviceMap.get(e);
3596
+ if (t) return this.deviceSessionsMap.get(t)?.find((t) => t.sessionId === e);
3597
+ }
3598
+ getHardwareDeviceId(e) {
3599
+ return this.sessionIdToHardwareDeviceMap.get(e);
3600
+ }
3601
+ getNodeGatewayClient(e) {
3602
+ return this.nodeGatewayClientsMap.get(e);
3603
+ }
3604
+ setNodeGatewayClient(e, t) {
3605
+ this.nodeGatewayClientsMap.set(e, t);
3606
+ }
3607
+ createNodeGatewayClient(e) {
3608
+ let t = new ei({
3609
+ sessionId: e.sessionId,
3610
+ hardwareDeviceId: e.hardwareDeviceId,
3611
+ deviceInfo: e.deviceInfo,
3612
+ onMessage: e.onMessage,
3613
+ onStatusEvent: e.onStatusEvent
3614
+ });
3615
+ return this.nodeGatewayClientsMap.set(e.sessionId, t), this.sessionIdToHardwareDeviceMap.set(e.sessionId, e.hardwareDeviceId), t;
3616
+ }
3617
+ closeNodeGatewayClient(e) {
3618
+ let t = this.nodeGatewayClientsMap.get(e);
3619
+ t && (t.stop(), this.nodeGatewayClientsMap.delete(e), this.removeSession(e), D().info(`[yoyoclaw-channel] closed node gateway client for session: ${e}`));
3620
+ }
3621
+ closePreviousNodeGatewayClients(e, t) {
3622
+ let n = this.deviceSessionsMap.get(e);
3623
+ if (!n || n.length === 0) return;
3624
+ let r = n.filter((e) => e.timestamp < t);
3625
+ if (r.length > 0) {
3626
+ D().info(`[yoyoclaw-channel] closing ${r.length} previous node gateway client(s) for hardware device: ${e}, new timestamp: ${t}`);
3627
+ for (let e of r) this.closeNodeGatewayClient(e.sessionId);
3628
+ }
3629
+ }
3630
+ closeAllNodeGatewayClients() {
3631
+ for (let [e, t] of this.nodeGatewayClientsMap.entries()) t.stop(), D().info(`[yoyoclaw-channel] closed node gateway client for session: ${e}`);
3632
+ this.nodeGatewayClientsMap.clear(), this.deviceSessionsMap.clear(), this.sessionIdToHardwareDeviceMap.clear();
3633
+ }
3634
+ hasSession(e) {
3635
+ return this.sessionIdToHardwareDeviceMap.has(e);
3636
+ }
3637
+ getSessionCount() {
3638
+ return this.sessionIdToHardwareDeviceMap.size;
3639
+ }
3640
+ }, ni = class {
3641
+ cloudClient;
3642
+ sessionManager;
3643
+ adminClientManager;
3644
+ messageHandler;
3645
+ config;
3646
+ constructor(e) {
3647
+ this.config = e, this.sessionManager = new ti(), this.adminClientManager = new Un({ onStatusEvent: this.handleStatusEvent }), this.messageHandler = new $r({
3648
+ sessionManager: this.sessionManager,
3649
+ adminClientManager: this.adminClientManager,
3650
+ config: {
3651
+ deviceInfo: e.deviceInfo,
3652
+ onStatusEvent: this.handleStatusEvent,
3653
+ onReply: (e) => this.cloudClient.send(e)
3654
+ }
3655
+ }), this.cloudClient = new $n({
3656
+ deviceInfo: e.deviceInfo,
3657
+ userInfo: e.userInfo,
3658
+ onMessage: this.messageHandler.handleCloudMessage,
3659
+ onOpen: this.handleCloudOpen,
3660
+ onClose: this.handleCloudClose,
3661
+ onRemoteDeviceOffline: this.handleRemoteDeviceOffline,
3662
+ onDeviceNotRegistered: this.handleDeviceNotRegistered,
3663
+ onUnauthorized: this.handleUnauthorized,
3664
+ onStatusEvent: this.handleStatusEvent
3665
+ }), this.adminClientManager.init();
3666
+ }
3667
+ start() {
3668
+ D().info("[yoyoclaw-channel] starting connection"), this.adminClientManager.ensureConnected(), this.cloudClient.connect();
3669
+ }
3670
+ destroy() {
3671
+ D().info("[yoyoclaw-channel] closing connection"), this.sessionManager.closeAllNodeGatewayClients(), this.adminClientManager.destroy(), this.cloudClient.close();
3672
+ }
3673
+ handleCloudOpen = () => {
3674
+ D().info("[yoyoclaw-channel] cloud connection established"), this.config.onOpen?.();
3675
+ };
3676
+ handleStatusEvent = (e) => {
3677
+ this.config.onStatusEvent?.(e);
3678
+ };
3679
+ handleCloudClose = () => {
3680
+ D().info("[yoyoclaw-channel] cloud connection closed"), this.config.onClose?.();
3681
+ };
3682
+ handleRemoteDeviceOffline = (e) => {
3683
+ this.sessionManager.closeNodeGatewayClient(e);
3684
+ };
3685
+ handleDeviceNotRegistered = () => {
3686
+ D().info("[yoyoclaw-channel] device not registered, notifying connection layer"), this.config.onDeviceNotRegistered?.();
3687
+ };
3688
+ handleUnauthorized = () => {
3689
+ D().info("[yoyoclaw-channel] unauthorized connection, notifying connection layer"), this.config.onUnauthorized?.();
3690
+ };
3691
+ }, Z = {
3692
+ channel: null,
3693
+ status: "idle"
3694
+ }, Q = null, ri = (e) => ({
3695
+ id: "yoyoclaw-connection",
3696
+ async start() {
3697
+ D().info("[yoyoclaw] plugin service enabled"), Q = new bn(!0);
3698
+ try {
3699
+ await Q.loadAndCleanStatus(), D().info("[yoyoclaw-conn] status tracker initialized and cleaned");
3700
+ } catch (e) {
3701
+ D().warn(`[yoyoclaw-conn] failed to load saved status: ${String(e)}`);
3702
+ }
3703
+ D().debug?.(`[yoyoclaw] agents: ${JSON.stringify(e.config.agents?.defaults)}`);
3704
+ try {
3705
+ await j().initializePluginConfig("yoyo"), D().info("[yoyoclaw] plugin config initialized");
3706
+ } catch (e) {
3707
+ D().error(`[yoyoclaw] failed to initialize plugin config: ${String(e)}`);
3708
+ }
3709
+ try {
3710
+ let e = await dn();
3711
+ e?.token ? (D().info("[yoyoclaw-conn] token found, creating channel"), await ii(await W(), e)) : D().info("[yoyoclaw-conn] no token found, skipping channel creation");
3712
+ } catch (e) {
3713
+ D().error(`[yoyoclaw-conn] failed to initialize connection: ${String(e)}`);
3714
+ }
3715
+ },
3716
+ async stop(e) {
3717
+ $(), D().info("[yoyoclaw-conn] stopping connection service"), Q &&= (await Q.destroy(), null);
3718
+ }
3719
+ });
3720
+ async function ii(e, t) {
3721
+ return Z.status = "connecting", D().info(`[yoyoclaw-conn] creating new channel for device: ${e.deviceId}`), Q && await Q.handleEvent({
3722
+ type: G.CONNECTION_STATUS_CHANGED,
3723
+ timestamp: Date.now(),
3724
+ data: {
3725
+ status: "connecting",
3726
+ previousStatus: Z.status
3727
+ }
3728
+ }), new Promise((n, r) => {
3729
+ Z.channel = new ni({
3730
+ deviceInfo: e,
3731
+ userInfo: t,
3732
+ onOpen: () => {
3733
+ Z.status = "connected", D().info("[yoyoclaw-conn] channel connected successfully"), Q && Q.handleEvent({
3734
+ type: G.CONNECTION_STATUS_CHANGED,
3735
+ timestamp: Date.now(),
3736
+ data: {
3737
+ status: "connected",
3738
+ previousStatus: "connecting"
3739
+ }
3740
+ }), n(void 0);
3741
+ },
3742
+ onClose: () => {
3743
+ Z.status = "idle", Z.channel = null, D().info("[yoyoclaw-conn] channel closed"), Q && Q.handleEvent({
3744
+ type: G.CONNECTION_STATUS_CHANGED,
3745
+ timestamp: Date.now(),
3746
+ data: {
3747
+ status: "idle",
3748
+ previousStatus: "connected"
3749
+ }
3750
+ }), n(void 0);
3751
+ },
3752
+ onDeviceNotRegistered: async () => {
3753
+ D().info("[yoyoclaw-conn] device not registered, handling...");
3754
+ let t = await dn();
3755
+ if (!t?.token) {
3756
+ D().info("[yoyoclaw-conn] no token available, treating as logout"), $();
3757
+ return;
3758
+ }
3759
+ try {
3760
+ D().info("[yoyoclaw-conn] attempting to register device"), await Bt(e, t), D().info("[yoyoclaw-conn] device registered successfully, reconnecting..."), $(), await ii(e, t);
3761
+ } catch (e) {
3762
+ D().error(`[yoyoclaw-conn] device registration failed: ${String(e)}`), D().info("[yoyoclaw-conn] clearing token and destroying channel");
3763
+ try {
3764
+ await fn();
3765
+ } catch (e) {
3766
+ D().error(`[yoyoclaw-conn] failed to clear token: ${String(e)}`);
3767
+ }
3768
+ $();
3769
+ }
3770
+ },
3771
+ onUnauthorized: async () => {
3772
+ D().warn("[yoyoclaw-conn] connection unauthorized (401), clearing token and destroying channel");
3773
+ try {
3774
+ await fn();
3775
+ } catch (e) {
3776
+ D().error(`[yoyoclaw-conn] failed to clear token: ${String(e)}`);
3777
+ }
3778
+ $();
3779
+ },
3780
+ onStatusEvent: async (e) => {
3781
+ Q && await Q.handleEvent(e);
3782
+ }
3783
+ });
3784
+ try {
3785
+ Z.channel.start();
3786
+ } catch (e) {
3787
+ Z.status = "idle", Z.channel = null, D().error(`[yoyoclaw-conn] failed to launch channel: ${String(e)}`), r(e);
3788
+ }
3789
+ });
3790
+ }
3791
+ function $() {
3792
+ try {
3793
+ if (!Z.channel) {
3794
+ D().warn("[yoyoclaw-conn] no channel to destroy");
3795
+ return;
3796
+ }
3797
+ D().info("[yoyoclaw-conn] destroying channel"), Z.channel.destroy(), Z.channel = null, Z.status = "idle", D().info("[yoyoclaw-conn] channel destroyed successfully");
3798
+ } catch (e) {
3799
+ D().error(`[yoyoclaw-conn] failed to destroy channel: ${String(e)}`);
3800
+ }
3801
+ }
3802
+ //#endregion
3803
+ //#region index.ts
3804
+ var ai = {
3805
+ id: "yoyo",
3806
+ name: "YOYOClaw",
3807
+ description: "OpenClaw Honor Yoyo connection plugin",
3808
+ configSchema: kn,
3809
+ register(e) {
3810
+ pe(e.runtime), Se(e.logger), e.registerService(ri(e)), e.on("before_prompt_build", async () => ({ prependSystemContext: En })), Tn(e);
3811
+ }
3812
+ };
3813
+ //#endregion
3814
+ export { ai as default };