@honor-claw/yoyo 1.3.0-alpha.3 → 1.3.0-alpha.4

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 (84) hide show
  1. package/dist/apis/claw-cloud.mjs +74 -0
  2. package/dist/apis/helpers.mjs +6 -0
  3. package/dist/apis/hosts.mjs +28 -0
  4. package/dist/apis/http-client.mjs +97 -0
  5. package/dist/apis/index.mjs +3 -0
  6. package/dist/cloud-channel/admin-client-manager.mjs +75 -0
  7. package/dist/cloud-channel/channel.mjs +60 -0
  8. package/dist/cloud-channel/client.mjs +160 -0
  9. package/dist/cloud-channel/message-handler.mjs +381 -0
  10. package/dist/cloud-channel/session-manager.mjs +71 -0
  11. package/dist/cloud-channel/utils.mjs +27 -0
  12. package/dist/commands/env/impl.mjs +31 -0
  13. package/dist/commands/env/index.mjs +1 -0
  14. package/dist/commands/index.mjs +17 -0
  15. package/dist/commands/login/impl.mjs +14 -0
  16. package/dist/commands/login/index.mjs +1 -0
  17. package/dist/commands/logout/impl.mjs +15 -0
  18. package/dist/commands/logout/index.mjs +1 -0
  19. package/dist/commands/status/index.mjs +58 -0
  20. package/dist/gateway-client/admin-client.mjs +54 -0
  21. package/dist/gateway-client/client.mjs +46 -0
  22. package/dist/gateway-client/node-client.mjs +49 -0
  23. package/dist/gateway-client/protocol-client.mjs +184 -0
  24. package/dist/gateway-client/types/client.mjs +32 -0
  25. package/dist/honor-auth/assets/favicon.mjs +4 -0
  26. package/dist/honor-auth/auth-result-html.mjs +213 -0
  27. package/dist/honor-auth/browser.mjs +47 -0
  28. package/dist/honor-auth/callback-server.mjs +101 -0
  29. package/dist/honor-auth/cloud.mjs +17 -0
  30. package/dist/honor-auth/config.mjs +27 -0
  31. package/dist/honor-auth/honor-auth-client.mjs +51 -0
  32. package/dist/honor-auth/index.mjs +4 -0
  33. package/dist/honor-auth/token-manager.mjs +64 -0
  34. package/dist/index.mjs +13 -3940
  35. package/dist/modules/configs/config-manager.mjs +298 -0
  36. package/dist/modules/configs/identity-persist.mjs +51 -0
  37. package/dist/modules/configs/index.mjs +2 -0
  38. package/dist/modules/configs/provider.mjs +136 -0
  39. package/dist/modules/device/auth.mjs +20 -0
  40. package/dist/modules/device/credential-builder.mjs +28 -0
  41. package/dist/modules/device/device-info.mjs +38 -0
  42. package/dist/modules/device/gateway-auth.mjs +16 -0
  43. package/dist/modules/device/helpers.mjs +13 -0
  44. package/dist/modules/device/identity.mjs +63 -0
  45. package/dist/modules/device/index.mjs +7 -0
  46. package/dist/modules/device/providers/index.mjs +28 -0
  47. package/dist/modules/device/providers/linux.mjs +33 -0
  48. package/dist/modules/device/providers/macos.mjs +25 -0
  49. package/dist/modules/device/providers/pad.mjs +68 -0
  50. package/dist/modules/device/providers/windows.mjs +79 -0
  51. package/dist/modules/device/registry.mjs +26 -0
  52. package/dist/modules/device-toolset/archive.mjs +39 -0
  53. package/dist/modules/device-toolset/artifacts.mjs +52 -0
  54. package/dist/modules/device-toolset/consts.mjs +5 -0
  55. package/dist/modules/device-toolset/copy-fallback.mjs +42 -0
  56. package/dist/modules/device-toolset/index.mjs +2 -0
  57. package/dist/modules/device-toolset/link.mjs +78 -0
  58. package/dist/modules/device-toolset/md5-index.mjs +71 -0
  59. package/dist/modules/device-toolset/normalize.mjs +39 -0
  60. package/dist/modules/device-toolset/persist.mjs +81 -0
  61. package/dist/modules/device-toolset/processor.mjs +42 -0
  62. package/dist/modules/device-toolset/skill-inject.mjs +50 -0
  63. package/dist/modules/login/impl.mjs +24 -0
  64. package/dist/modules/prompt/index.mjs +4 -0
  65. package/dist/runtime.mjs +23 -0
  66. package/dist/schemas.mjs +33 -0
  67. package/dist/services/connection/impl.mjs +148 -0
  68. package/dist/services/connection/index.mjs +1 -0
  69. package/dist/services/connection/status-tracker/events.mjs +6 -0
  70. package/dist/services/connection/status-tracker/index.mjs +4 -0
  71. package/dist/services/connection/status-tracker/storage.mjs +49 -0
  72. package/dist/services/connection/status-tracker/tracker.mjs +142 -0
  73. package/dist/services/connection/status-tracker/types.mjs +36 -0
  74. package/dist/utils/env.mjs +29 -0
  75. package/dist/utils/error.mjs +7 -0
  76. package/dist/utils/fs-safe.mjs +216 -0
  77. package/dist/utils/hash.mjs +10 -0
  78. package/dist/utils/home-dir.mjs +40 -0
  79. package/dist/utils/id.mjs +8 -0
  80. package/dist/utils/logger.mjs +15 -0
  81. package/dist/utils/proxy.mjs +18 -0
  82. package/dist/utils/version.mjs +7 -0
  83. package/dist/utils/ws.mjs +7 -0
  84. package/package.json +1 -1
@@ -0,0 +1,74 @@
1
+ import { uuid as e } from "../utils/id.mjs";
2
+ import { isOKResponse as t } from "./helpers.mjs";
3
+ import { takeApiHost as n } from "./hosts.mjs";
4
+ import { HttpClient as r } from "./http-client.mjs";
5
+ //#region src/apis/claw-cloud.ts
6
+ var i = class {
7
+ httpClient;
8
+ constructor(e, t) {
9
+ this.httpClient = new r(e, t);
10
+ }
11
+ async registerDevice(t, n, r) {
12
+ let i = {
13
+ "x-trace-id": e(),
14
+ "x-jwt-token": n.token,
15
+ "x-device-id": t.deviceId
16
+ }, a = {
17
+ businessTag: "YOYO_CLAW",
18
+ role: "yoyoclaw",
19
+ deviceInfo: {
20
+ ...t,
21
+ manufacture: t.manufacture,
22
+ brand: t.brand,
23
+ bizExtInfo: r
24
+ }
25
+ };
26
+ return this.httpClient.post("/v1/device/registry", {
27
+ headers: i,
28
+ body: a
29
+ });
30
+ }
31
+ async logoutDevice(t, n) {
32
+ let r = {
33
+ "x-trace-id": e(),
34
+ "x-jwt-token": n.token,
35
+ "x-device-id": t.deviceId
36
+ }, i = {
37
+ businessTag: "YOYO_CLAW",
38
+ deviceInfo: {
39
+ ...t,
40
+ manufacture: t.manufacture,
41
+ brand: t.brand
42
+ }
43
+ };
44
+ return this.httpClient.post("/v1/user/logout", {
45
+ headers: r,
46
+ body: i
47
+ });
48
+ }
49
+ async exchangeToken(n, r) {
50
+ let i = e(), a = {
51
+ "Content-Type": "application/json",
52
+ "x-device-id": n.deviceId,
53
+ "x-trace-id": i
54
+ }, o = {};
55
+ "userId" in r ? a["x-agw-userId"] = r.userId : o = {
56
+ clientId: r.authConfig.clientId,
57
+ code: r.code,
58
+ redirectUri: "http://127.0.0.1:8081/deepLink"
59
+ };
60
+ let s = await this.httpClient.post("/v1/user/jwtToken", {
61
+ body: o,
62
+ headers: a,
63
+ timeout: 15e3
64
+ });
65
+ if (t(s) && s.data.data) return s.data.data;
66
+ throw Error(`failed to get token: ${JSON.stringify(s.data)}, traceId: ${i}`);
67
+ }
68
+ };
69
+ function a() {
70
+ let e = n();
71
+ return new i(`https://${e.clawCloud}/aicloud/yoyo-claw-service`, e.grayTag ? { defaultHeaders: { "x-gray": e.grayTag } } : void 0);
72
+ }
73
+ //#endregion
74
+ export { i as ClawCloudClient, a as createClawCloudClient };
@@ -0,0 +1,6 @@
1
+ //#region src/apis/helpers.ts
2
+ function e(e) {
3
+ return e.status >= 200 && e.status < 300 && e.data.code === "1";
4
+ }
5
+ //#endregion
6
+ export { e as isOKResponse };
@@ -0,0 +1,28 @@
1
+ import { getYoyoEnvInfo as e } from "../runtime.mjs";
2
+ //#region src/apis/hosts.ts
3
+ function t() {
4
+ let t = e(), n;
5
+ switch (t.env) {
6
+ case "dev":
7
+ n = {
8
+ clawCloud: "omni-dev-drcn.hiboard.hihonorcloud.com",
9
+ ics: "api-agd-test-drcn.hiboard.hihonorcloud.com"
10
+ };
11
+ break;
12
+ case "test":
13
+ n = {
14
+ clawCloud: "omni-pre-drcn.hiboard.hihonorcloud.com",
15
+ ics: "api-agd-test-drcn.hiboard.hihonorcloud.com"
16
+ };
17
+ break;
18
+ default:
19
+ n = {
20
+ clawCloud: "yoyoclaw-drcn.hiboard.hihonorcloud.com",
21
+ ics: "api-prd-drcn.hiboard.hihonorcloud.com"
22
+ };
23
+ break;
24
+ }
25
+ return t.grayTag && (n.grayTag = t.grayTag), n;
26
+ }
27
+ //#endregion
28
+ export { t as takeApiHost };
@@ -0,0 +1,97 @@
1
+ import { wrapError as e } from "../utils/error.mjs";
2
+ import { getProxyUrl as t, shouldUseProxy as n } from "../utils/proxy.mjs";
3
+ import { ProxyAgent as r, request as i } from "undici";
4
+ //#region src/apis/http-client.ts
5
+ var a = class extends Error {
6
+ constructor(e, t, n) {
7
+ super(n), this.status = e, this.data = t, this.name = "HttpError";
8
+ }
9
+ }, o = class {
10
+ baseUrl;
11
+ defaultHeaders;
12
+ defaultTimeout;
13
+ proxyAgent;
14
+ constructor(e, n) {
15
+ this.baseUrl = e.replace(/\/$/, ""), this.defaultHeaders = n?.defaultHeaders || {}, this.defaultTimeout = n?.defaultTimeout || 3e4;
16
+ let i = t(n?.proxy);
17
+ i && (this.proxyAgent = new r(i));
18
+ }
19
+ async request(r) {
20
+ let { method: o = "GET", headers: s = {}, body: c, timeout: l = this.defaultTimeout, query: u } = r, d = r.url;
21
+ if (!d.startsWith("http://") && !d.startsWith("https://") && (d = `${this.baseUrl}${d.startsWith("/") ? "" : "/"}${d}`), u && Object.keys(u).length > 0) {
22
+ let e = new URLSearchParams();
23
+ Object.entries(u).forEach(([t, n]) => {
24
+ n !== void 0 && e.append(t, String(n));
25
+ });
26
+ let t = e.toString();
27
+ t && (d += (d.includes("?") ? "&" : "?") + t);
28
+ }
29
+ let f = {
30
+ ...this.defaultHeaders,
31
+ ...s
32
+ };
33
+ c && !f["Content-Type"] && (f["Content-Type"] = "application/json");
34
+ let p;
35
+ c != null && (p = typeof c == "string" ? c : JSON.stringify(c));
36
+ try {
37
+ let e = n(t(), r.disableProxy) && this.proxyAgent ? this.proxyAgent : void 0, s = await i(d, {
38
+ method: o,
39
+ headers: f,
40
+ body: p,
41
+ headersTimeout: l,
42
+ bodyTimeout: l,
43
+ dispatcher: e
44
+ }), c = await s.body.text(), u;
45
+ try {
46
+ u = c ? JSON.parse(c) : {};
47
+ } catch {
48
+ u = c;
49
+ }
50
+ if (s.statusCode >= 200 && s.statusCode < 300) return {
51
+ data: u,
52
+ status: s.statusCode,
53
+ headers: s.headers
54
+ };
55
+ throw new a(s.statusCode, u, `HTTP request failed with status ${s.statusCode}`);
56
+ } catch (t) {
57
+ throw t instanceof a ? t : e(t, "HTTP request failed");
58
+ }
59
+ }
60
+ async get(e, t) {
61
+ return this.request({
62
+ ...t,
63
+ url: e,
64
+ method: "GET"
65
+ });
66
+ }
67
+ async post(e, t) {
68
+ return this.request({
69
+ ...t,
70
+ url: e,
71
+ method: "POST"
72
+ });
73
+ }
74
+ async put(e, t) {
75
+ return this.request({
76
+ ...t,
77
+ url: e,
78
+ method: "PUT"
79
+ });
80
+ }
81
+ async delete(e, t) {
82
+ return this.request({
83
+ ...t,
84
+ url: e,
85
+ method: "DELETE"
86
+ });
87
+ }
88
+ async patch(e, t) {
89
+ return this.request({
90
+ ...t,
91
+ url: e,
92
+ method: "PATCH"
93
+ });
94
+ }
95
+ };
96
+ //#endregion
97
+ export { o as HttpClient, a as HttpError };
@@ -0,0 +1,3 @@
1
+ import "./helpers.mjs";
2
+ import "./http-client.mjs";
3
+ import "./claw-cloud.mjs";
@@ -0,0 +1,75 @@
1
+ import { useClawLogger as e } from "../utils/logger.mjs";
2
+ import { getConfigManager as t } from "../modules/configs/config-manager.mjs";
3
+ import { StatusEventType as n } from "../services/connection/status-tracker/events.mjs";
4
+ import r from "../gateway-client/admin-client.mjs";
5
+ //#region src/cloud-channel/admin-client-manager.ts
6
+ var i = class {
7
+ client = null;
8
+ ready = !1;
9
+ options;
10
+ pendingReadyRequests = /* @__PURE__ */ new Map();
11
+ requestIdCounter = 0;
12
+ constructor(e = {}) {
13
+ this.options = e;
14
+ }
15
+ init() {
16
+ if (this.client !== null) return;
17
+ let i = t().getGatewayAuthConfig(), a = typeof i?.token == "string" ? i.token : "", o = typeof i?.password == "string" ? i.password : "";
18
+ this.client = new r({
19
+ token: a,
20
+ password: o,
21
+ onAuthenticated: () => {
22
+ e().info("[yoyoclaw-channel] admin gateway client authenticated"), this.ready = !0, this.resolveAllPending(!0);
23
+ },
24
+ onClose: (t) => {
25
+ e().info(`[yoyoclaw-channel] admin gateway client closed: ${t}`), this.ready = !1;
26
+ },
27
+ onReconnectFailed: () => {
28
+ e().error("[yoyoclaw-channel] admin gateway client reconnect failed, notifying status tracker"), this.options.onStatusEvent?.({
29
+ type: n.ADMIN_CLIENT_RECONNECT_FAILED,
30
+ timestamp: Date.now(),
31
+ data: {}
32
+ });
33
+ }
34
+ });
35
+ }
36
+ connect() {
37
+ this.client?.connect();
38
+ }
39
+ destroy() {
40
+ this.client &&= (this.client.stop(), null), this.ready = !1, this.cancelAllPending(), e().info("[yoyoclaw-channel] admin gateway client closed");
41
+ }
42
+ cancelAllPending() {
43
+ for (let [e, t] of this.pendingReadyRequests) clearTimeout(t.timeout), t.resolve(!1);
44
+ this.pendingReadyRequests.clear();
45
+ }
46
+ isReady() {
47
+ return this.ready;
48
+ }
49
+ getClient() {
50
+ return this.client;
51
+ }
52
+ canOperate() {
53
+ return this.client !== null && this.ready;
54
+ }
55
+ ensureConnected() {
56
+ return this.client === null && (e().info("[yoyoclaw-channel] admin gateway client is null, initializing"), this.init()), this.ready || (e().info("[yoyoclaw-channel] admin gateway client not ready, connecting"), this.connect()), this.canOperate();
57
+ }
58
+ waitForReady(t = 5e3) {
59
+ return this.canOperate() ? Promise.resolve(!0) : new Promise((n) => {
60
+ let r = `req_${++this.requestIdCounter}`, i = setTimeout(() => {
61
+ this.pendingReadyRequests.delete(r), this.pendingReadyRequests.size === 0 && e().warn("[yoyoclaw-channel] admin gateway client waitForReady timeout, all requests rejected"), n(!1);
62
+ }, t);
63
+ this.pendingReadyRequests.set(r, {
64
+ resolve: n,
65
+ timeout: i
66
+ }), this.ensureConnected();
67
+ });
68
+ }
69
+ resolveAllPending(e) {
70
+ for (let [t, n] of this.pendingReadyRequests) clearTimeout(n.timeout), n.resolve(e);
71
+ this.pendingReadyRequests.clear();
72
+ }
73
+ };
74
+ //#endregion
75
+ export { i as AdminClientManager };
@@ -0,0 +1,60 @@
1
+ import { useClawLogger as e } from "../utils/logger.mjs";
2
+ import { AdminClientManager as t } from "./admin-client-manager.mjs";
3
+ import { ClawCloudSocketClient as n } from "./client.mjs";
4
+ import { MessageHandler as r } from "./message-handler.mjs";
5
+ import { SessionManager as i } from "./session-manager.mjs";
6
+ //#region src/cloud-channel/channel.ts
7
+ var a = class {
8
+ cloudClient;
9
+ sessionManager;
10
+ adminClientManager;
11
+ messageHandler;
12
+ config;
13
+ constructor(e) {
14
+ this.config = e, this.sessionManager = new i(), this.adminClientManager = new t({ onStatusEvent: this.handleStatusEvent }), this.messageHandler = new r({
15
+ sessionManager: this.sessionManager,
16
+ adminClientManager: this.adminClientManager,
17
+ config: {
18
+ deviceInfo: e.deviceInfo,
19
+ onStatusEvent: this.handleStatusEvent,
20
+ onReply: (e) => this.cloudClient.send(e)
21
+ }
22
+ }), this.cloudClient = new n({
23
+ deviceInfo: e.deviceInfo,
24
+ userInfo: e.userInfo,
25
+ onMessage: this.messageHandler.handleCloudMessage,
26
+ onOpen: this.handleCloudOpen,
27
+ onClose: this.handleCloudClose,
28
+ onRemoteDeviceOffline: this.handleRemoteDeviceOffline,
29
+ onDeviceNotRegistered: this.handleDeviceNotRegistered,
30
+ onUnauthorized: this.handleUnauthorized,
31
+ onStatusEvent: this.handleStatusEvent
32
+ }), this.adminClientManager.init();
33
+ }
34
+ start() {
35
+ e().info("[yoyoclaw-channel] starting connection"), this.adminClientManager.ensureConnected(), this.cloudClient.connect();
36
+ }
37
+ destroy() {
38
+ e().info("[yoyoclaw-channel] closing connection"), this.sessionManager.closeAllNodeGatewayClients(), this.adminClientManager.destroy(), this.cloudClient.close();
39
+ }
40
+ handleCloudOpen = () => {
41
+ e().info("[yoyoclaw-channel] cloud connection established"), this.config.onOpen?.();
42
+ };
43
+ handleStatusEvent = (e) => {
44
+ this.config.onStatusEvent?.(e);
45
+ };
46
+ handleCloudClose = () => {
47
+ e().info("[yoyoclaw-channel] cloud connection closed"), this.config.onClose?.();
48
+ };
49
+ handleRemoteDeviceOffline = (e) => {
50
+ this.sessionManager.closeNodeGatewayClient(e);
51
+ };
52
+ handleDeviceNotRegistered = () => {
53
+ e().info("[yoyoclaw-channel] device not registered, notifying connection layer"), this.config.onDeviceNotRegistered?.();
54
+ };
55
+ handleUnauthorized = () => {
56
+ e().info("[yoyoclaw-channel] unauthorized connection, notifying connection layer"), this.config.onUnauthorized?.();
57
+ };
58
+ };
59
+ //#endregion
60
+ export { a as ClawChannel };
@@ -0,0 +1,160 @@
1
+ import { useClawLogger as e } from "../utils/logger.mjs";
2
+ import { StatusEventType as t } from "../services/connection/status-tracker/events.mjs";
3
+ import { rawDataToString as n } from "../utils/ws.mjs";
4
+ import { buildCloudSocketConnectParams as r } from "./utils.mjs";
5
+ import i from "ws";
6
+ //#region src/cloud-channel/client.ts
7
+ var a = 3e4, o = 4e3, s = 1e3, c = 2, l = 999, u = class {
8
+ ws = null;
9
+ options;
10
+ retryCount = 0;
11
+ retryTimer = null;
12
+ isManualClose = !1;
13
+ isRetryPaused = !1;
14
+ pingTimer = null;
15
+ currentTraceId = "";
16
+ constructor(e) {
17
+ this.options = e;
18
+ }
19
+ connect(e = !1) {
20
+ if (this.ws?.readyState === i.OPEN) return;
21
+ this.clearRetryTimer();
22
+ let { deviceInfo: n, userInfo: a } = this.options, { url: o, traceId: s, wsOptions: c } = r(n, a);
23
+ this.currentTraceId = s, this.options.onStatusEvent?.({
24
+ type: t.CLOUD_SOCKET_CONNECTING,
25
+ timestamp: Date.now(),
26
+ data: { url: o }
27
+ }), this.ws = new i(o, c), this.ws.on("open", this.handleOpen.bind(this, o, 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);
28
+ }
29
+ handleOpen = (n, r) => {
30
+ let i = r ? "reconnected" : "connected";
31
+ e().info(`[claw-cloud-socket][${this.currentTraceId}] ${i} to ${n.slice(0, 15)}`), this.clearRetryTimer(), this.isManualClose = !1, this.retryCount = 0, this.isRetryPaused = !1, this.startPingTimer(), this.options.onStatusEvent?.({
32
+ type: t.CLOUD_SOCKET_CONNECTED,
33
+ timestamp: Date.now(),
34
+ data: {
35
+ url: n,
36
+ connectedAt: (/* @__PURE__ */ new Date()).toISOString()
37
+ }
38
+ }), this.options.onOpen?.();
39
+ };
40
+ handlePong = () => {
41
+ e().debug?.("[claw-cloud-socket] received pong from server");
42
+ };
43
+ handleClose = (n, r) => {
44
+ let i = r.toString();
45
+ e().info(`[claw-cloud-socket][${this.currentTraceId}] connection closed: ${n} - ${i}`), this.options.onStatusEvent?.({
46
+ type: t.CLOUD_SOCKET_DISCONNECTED,
47
+ timestamp: Date.now(),
48
+ data: {
49
+ reason: i,
50
+ code: n,
51
+ disconnectedAt: (/* @__PURE__ */ new Date()).toISOString()
52
+ }
53
+ }), this.isManualClose ? (this.stopPingTimer(), this.options.onClose?.()) : this.scheduleReconnect();
54
+ };
55
+ handleError = (n) => {
56
+ e().error(`[claw-cloud-socket][${this.currentTraceId}] connect errorred: ${n.message}`), n.message.includes("401") && (e().warn(`[claw-cloud-socket][${this.currentTraceId}] unauthorized connection (401), pausing retry and notifying client`), this.pauseRetry(), this.options.onUnauthorized?.()), this.options.onStatusEvent?.({
57
+ type: t.CLOUD_SOCKET_ERROR,
58
+ timestamp: Date.now(),
59
+ data: {
60
+ error: n.message,
61
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
62
+ }
63
+ });
64
+ };
65
+ send(t) {
66
+ if (!this.ws || this.ws.readyState !== i.OPEN) return e().error("[claw-cloud-socket] cannot send message: connection not open"), !1;
67
+ try {
68
+ let e = JSON.stringify(t);
69
+ return this.ws.send(e), !0;
70
+ } catch (n) {
71
+ return e().error(`[claw-cloud-socket] failed to send message to cloud session ${t.targetDeviceId},
72
+ ${n instanceof Error ? n.message : String(n)}`), !1;
73
+ }
74
+ }
75
+ close() {
76
+ this.isManualClose = !0, this.reset(), this.ws &&= (this.ws.close(), null);
77
+ }
78
+ reset() {
79
+ this.clearRetryTimer(), this.stopPingTimer();
80
+ }
81
+ onMessage = async (t) => {
82
+ try {
83
+ let r = n(t), i = JSON.parse(r);
84
+ if (e().debug?.(`[yoyoclaw-channel] received cloud message from session ${i.wsOutputEvent?.sourceDeviceId}, deviceId ${i.wsOutputEvent?.sourceDeviceInfo?.deviceId || "nil"}, ${r.slice(0, 3e3)}`), i.code === "YOYO_CLAW_100000") {
85
+ if (i.wsOutputEvent) {
86
+ i.sessionInfo && (i.wsOutputEvent.sessionInfo = i.sessionInfo), this.options.onMessage?.(i.wsOutputEvent);
87
+ return;
88
+ }
89
+ } else if (i.code === "YOYO_CLAW_100002") {
90
+ if (i.extData?.offlineSocketId) {
91
+ e().info(`[claw-cloud-socket] remote device offline, session: ${i.extData.offlineSocketId}`), this.options.onRemoteDeviceOffline?.(i.extData.offlineSocketId);
92
+ return;
93
+ }
94
+ } else if (i.code === "YOYO_CLAW_100001") {
95
+ this.pauseRetry(), e().info("[claw-cloud-socket] device not registered, closing connection"), this.options.onDeviceNotRegistered?.();
96
+ return;
97
+ }
98
+ e().warn(`[claw-cloud-socket] unexpected message: ${i.cnMessage}, code: ${i.code}`);
99
+ } catch (t) {
100
+ e().error(`[claw-cloud-socket] failed to parse message: ${t instanceof Error ? t.message : String(t)}`);
101
+ }
102
+ };
103
+ scheduleReconnect() {
104
+ if (this.isRetryPaused) {
105
+ e().info("[claw-cloud-socket] retry paused, skipping reconnect"), this.reset(), this.options.onClose?.();
106
+ return;
107
+ }
108
+ this.clearRetryTimer();
109
+ let n = this.calculateRetryDelay();
110
+ this.retryCount = Math.min(this.retryCount + 1, l), e().info(`[claw-cloud-socket] scheduling reconnect attempt ${this.retryCount} in ${n}ms`), this.options.onStatusEvent?.({
111
+ type: t.CLOUD_SOCKET_RETRY,
112
+ timestamp: Date.now(),
113
+ data: {
114
+ retryCount: this.retryCount,
115
+ delay: n
116
+ }
117
+ }), this.retryTimer = setTimeout(() => {
118
+ this.connect(!0);
119
+ }, n);
120
+ }
121
+ clearRetryTimer() {
122
+ this.retryTimer &&= (clearTimeout(this.retryTimer), null);
123
+ }
124
+ calculateRetryDelay() {
125
+ let e = s * c ** +Math.min(this.retryCount, 2);
126
+ return Math.min(e, o);
127
+ }
128
+ startPingTimer() {
129
+ this.pingTimer = setInterval(() => {
130
+ if (!this.ws || this.ws.readyState !== i.OPEN) {
131
+ this.stopPingTimer();
132
+ return;
133
+ }
134
+ this.ws.ping(), e().debug?.("[claw-cloud-socket] sent ping to server");
135
+ let { deviceInfo: t } = this.options, n = {
136
+ msgType: "pingMessage",
137
+ sourceRole: "yoyoclaw",
138
+ sourceDeviceId: t.deviceId,
139
+ targetRole: "node",
140
+ port: t.port
141
+ };
142
+ try {
143
+ this.ws.send(JSON.stringify(n)), e().debug?.("[claw-cloud-socket] sent pingMessage to server");
144
+ } catch {
145
+ e().error("[claw-cloud-socket] failed to send pingMessage");
146
+ }
147
+ }, a);
148
+ }
149
+ stopPingTimer() {
150
+ this.pingTimer &&= (clearInterval(this.pingTimer), null);
151
+ }
152
+ pauseRetry() {
153
+ this.isRetryPaused || (this.isRetryPaused = !0, this.clearRetryTimer(), e().info("[claw-cloud-socket] retry paused"));
154
+ }
155
+ resumeRetry() {
156
+ this.isRetryPaused && (this.isRetryPaused = !1, e().info("[claw-cloud-socket] retry resumed"), (!this.ws || this.ws.readyState !== i.OPEN) && (this.retryCount = 0, this.connect(!0)));
157
+ }
158
+ };
159
+ //#endregion
160
+ export { u as ClawCloudSocketClient };