@honor-claw/yoyo 1.1.2 → 1.1.4-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +25 -25
- package/package.json +5 -5
- package/src/apis/claw-cloud.ts +124 -124
- package/src/apis/helpers.ts +10 -10
- package/src/apis/honor-auth.ts +158 -158
- package/src/apis/http-client.ts +239 -239
- package/src/apis/index.ts +8 -8
- package/src/apis/types.ts +77 -73
- package/src/cloud-channel/channel.ts +117 -117
- package/src/cloud-channel/client.ts +3 -3
- package/src/cloud-channel/index.ts +4 -4
- package/src/cloud-channel/message-handler.ts +50 -42
- package/src/cloud-channel/session-manager.ts +14 -9
- package/src/cloud-channel/types.ts +115 -115
- package/src/commands/env/impl.ts +58 -58
- package/src/commands/env/index.ts +1 -1
- package/src/commands/index.ts +30 -30
- package/src/commands/login/impl.ts +30 -30
- package/src/commands/login/index.ts +1 -1
- package/src/commands/logout/index.ts +1 -1
- package/src/commands/status/index.ts +194 -194
- package/src/gateway-client/client.ts +90 -90
- package/src/gateway-client/device/auth.ts +57 -57
- package/src/gateway-client/device/builder.ts +105 -105
- package/src/gateway-client/device/helpers.ts +40 -40
- package/src/gateway-client/device/identity.ts +251 -251
- package/src/gateway-client/device/index.ts +40 -40
- package/src/gateway-client/device/types.ts +57 -57
- package/src/gateway-client/index.ts +5 -5
- package/src/gateway-client/protocol-client.ts +49 -34
- package/src/honor-auth/browser.ts +2 -2
- package/src/honor-auth/callback-server.ts +109 -109
- package/src/honor-auth/cloud.ts +57 -57
- package/src/honor-auth/config.ts +43 -43
- package/src/honor-auth/index.ts +3 -3
- package/src/honor-auth/token-manager.ts +90 -90
- package/src/honor-auth/types.ts +50 -50
- package/src/index.ts +10 -10
- package/src/modules/claw-configs/config-manager.ts +409 -409
- package/src/modules/claw-configs/hosts.ts +48 -48
- package/src/modules/claw-configs/index.ts +8 -8
- package/src/modules/claw-configs/provider.ts +394 -394
- package/src/modules/claw-configs/types.ts +34 -34
- package/src/modules/device/device-info.ts +1 -1
- package/src/modules/device/index.ts +3 -3
- package/src/modules/device/providers/base.ts +32 -32
- package/src/modules/device/providers/pad.ts +107 -107
- package/src/modules/device/providers/windows.ts +130 -130
- package/src/modules/device/registry.ts +48 -43
- package/src/modules/login/impl.ts +31 -26
- package/src/modules/login/index.ts +6 -6
- package/src/schemas.ts +23 -23
- package/src/services/connection/impl.ts +339 -339
- package/src/services/connection/status-tracker/events.ts +127 -127
- package/src/services/connection/status-tracker/index.ts +31 -31
- package/src/services/connection/status-tracker/storage.ts +133 -133
- package/src/services/connection/status-tracker/tracker.ts +370 -370
- package/src/services/connection/status-tracker/types.ts +131 -131
- package/src/services/connection/types.ts +20 -20
- package/src/types.ts +64 -64
- package/src/utils/id.ts +8 -8
- package/src/utils/jwt.ts +37 -37
- package/src/utils/logger.ts +20 -20
- package/src/utils/proxy.ts +58 -58
- package/src/utils/version.ts +29 -29
- package/src/utils/ws.ts +21 -21
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
import type { ClawChannelConfig } from "./types.js";
|
|
2
|
-
import { ClawCloudSocketClient } from "./client.js";
|
|
3
|
-
import { SessionManager } from "./session-manager.js";
|
|
4
|
-
import { AdminClientManager } from "./admin-client-manager.js";
|
|
5
|
-
import { MessageHandler } from "./message-handler.js";
|
|
6
|
-
import { useClawLogger } from "../utils/logger.js";
|
|
7
|
-
import { takeApiHost } from "../modules/claw-configs/hosts.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 新的Channel实现
|
|
11
|
-
* - 使用ClawCloudSocketClient连接云侧服务器
|
|
12
|
-
* - 处理配对消息和用户消息
|
|
13
|
-
* - 管理GatewayClient连接
|
|
14
|
-
*/
|
|
15
|
-
export class ClawChannel {
|
|
16
|
-
private cloudClient: ClawCloudSocketClient;
|
|
17
|
-
private sessionManager: SessionManager;
|
|
18
|
-
private adminClientManager: AdminClientManager;
|
|
19
|
-
private messageHandler: MessageHandler;
|
|
20
|
-
private config: ClawChannelConfig;
|
|
21
|
-
|
|
22
|
-
constructor(config: ClawChannelConfig) {
|
|
23
|
-
this.config = config;
|
|
24
|
-
const hosts = takeApiHost();
|
|
25
|
-
|
|
26
|
-
this.sessionManager = new SessionManager();
|
|
27
|
-
this.adminClientManager = new AdminClientManager({
|
|
28
|
-
onStatusEvent: this.handleStatusEvent,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const extraHeaders = hosts.grayTag ? { 'x-gray': hosts.grayTag } : undefined;
|
|
32
|
-
|
|
33
|
-
this.cloudClient = new ClawCloudSocketClient({
|
|
34
|
-
serverUrl: `wss://${hosts.clawCloud}/aicloud/yoyo-claw-service/v1/yoyoclaw/fullduplex`,
|
|
35
|
-
deviceInfo: config.deviceInfo,
|
|
36
|
-
userInfo: config.userInfo,
|
|
37
|
-
extraHeaders,
|
|
38
|
-
onStatusEvent: this.handleStatusEvent,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
this.messageHandler = new MessageHandler({
|
|
42
|
-
sessionManager: this.sessionManager,
|
|
43
|
-
adminClientManager: this.adminClientManager,
|
|
44
|
-
cloudClient: this.cloudClient,
|
|
45
|
-
config: {
|
|
46
|
-
deviceInfo: {
|
|
47
|
-
deviceId: config.deviceInfo.deviceId,
|
|
48
|
-
port: config.deviceInfo.port,
|
|
49
|
-
},
|
|
50
|
-
onStatusEvent: this.handleStatusEvent,
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
this.cloudClient.setMessageHandler(this.messageHandler.handleCloudMessage);
|
|
55
|
-
this.cloudClient.setOpenHandler(this.handleCloudOpen);
|
|
56
|
-
this.cloudClient.setCloseHandler(this.handleCloudClose);
|
|
57
|
-
this.cloudClient.setRemoteDeviceOfflineHandler(this.handleRemoteDeviceOffline);
|
|
58
|
-
this.cloudClient.setDeviceNotRegisteredHandler(this.handleDeviceNotRegistered);
|
|
59
|
-
|
|
60
|
-
// 实例化AdminGatewayClient
|
|
61
|
-
this.adminClientManager.init();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
start(): void {
|
|
65
|
-
useClawLogger().info("[yoyoclaw-channel] starting connection");
|
|
66
|
-
this.adminClientManager.ensureConnected();
|
|
67
|
-
this.cloudClient.connect();
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* 关闭连接
|
|
72
|
-
*/
|
|
73
|
-
destroy(): void {
|
|
74
|
-
useClawLogger().info("[yoyoclaw-channel] closing connection");
|
|
75
|
-
this.sessionManager.closeAllNodeGatewayClients();
|
|
76
|
-
this.adminClientManager.destroy();
|
|
77
|
-
this.cloudClient.close();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* 处理云侧连接打开
|
|
82
|
-
*/
|
|
83
|
-
private handleCloudOpen = () => {
|
|
84
|
-
useClawLogger().info("[yoyoclaw-channel] cloud connection established");
|
|
85
|
-
this.config.onOpen?.();
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* 统一处理所有状态事件
|
|
90
|
-
*/
|
|
91
|
-
private handleStatusEvent = (event: any) => {
|
|
92
|
-
this.config.onStatusEvent?.(event);
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* 处理云侧连接关闭
|
|
97
|
-
*/
|
|
98
|
-
private handleCloudClose = () => {
|
|
99
|
-
useClawLogger().info("[yoyoclaw-channel] cloud connection closed");
|
|
100
|
-
this.config.onClose?.();
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* 处理对向设备离线
|
|
105
|
-
*/
|
|
106
|
-
private handleRemoteDeviceOffline = (sourceDeviceId: string) => {
|
|
107
|
-
this.sessionManager.closeNodeGatewayClient(sourceDeviceId);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* 处理当前设备未注册
|
|
112
|
-
*/
|
|
113
|
-
private handleDeviceNotRegistered = () => {
|
|
114
|
-
useClawLogger().info("[yoyoclaw-channel] device not registered, notifying connection layer");
|
|
115
|
-
this.config.onDeviceNotRegistered?.();
|
|
116
|
-
};
|
|
117
|
-
}
|
|
1
|
+
import type { ClawChannelConfig } from "./types.js";
|
|
2
|
+
import { ClawCloudSocketClient } from "./client.js";
|
|
3
|
+
import { SessionManager } from "./session-manager.js";
|
|
4
|
+
import { AdminClientManager } from "./admin-client-manager.js";
|
|
5
|
+
import { MessageHandler } from "./message-handler.js";
|
|
6
|
+
import { useClawLogger } from "../utils/logger.js";
|
|
7
|
+
import { takeApiHost } from "../modules/claw-configs/hosts.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 新的Channel实现
|
|
11
|
+
* - 使用ClawCloudSocketClient连接云侧服务器
|
|
12
|
+
* - 处理配对消息和用户消息
|
|
13
|
+
* - 管理GatewayClient连接
|
|
14
|
+
*/
|
|
15
|
+
export class ClawChannel {
|
|
16
|
+
private cloudClient: ClawCloudSocketClient;
|
|
17
|
+
private sessionManager: SessionManager;
|
|
18
|
+
private adminClientManager: AdminClientManager;
|
|
19
|
+
private messageHandler: MessageHandler;
|
|
20
|
+
private config: ClawChannelConfig;
|
|
21
|
+
|
|
22
|
+
constructor(config: ClawChannelConfig) {
|
|
23
|
+
this.config = config;
|
|
24
|
+
const hosts = takeApiHost();
|
|
25
|
+
|
|
26
|
+
this.sessionManager = new SessionManager();
|
|
27
|
+
this.adminClientManager = new AdminClientManager({
|
|
28
|
+
onStatusEvent: this.handleStatusEvent,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const extraHeaders = hosts.grayTag ? { 'x-gray': hosts.grayTag } : undefined;
|
|
32
|
+
|
|
33
|
+
this.cloudClient = new ClawCloudSocketClient({
|
|
34
|
+
serverUrl: `wss://${hosts.clawCloud}/aicloud/yoyo-claw-service/v1/yoyoclaw/fullduplex`,
|
|
35
|
+
deviceInfo: config.deviceInfo,
|
|
36
|
+
userInfo: config.userInfo,
|
|
37
|
+
extraHeaders,
|
|
38
|
+
onStatusEvent: this.handleStatusEvent,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
this.messageHandler = new MessageHandler({
|
|
42
|
+
sessionManager: this.sessionManager,
|
|
43
|
+
adminClientManager: this.adminClientManager,
|
|
44
|
+
cloudClient: this.cloudClient,
|
|
45
|
+
config: {
|
|
46
|
+
deviceInfo: {
|
|
47
|
+
deviceId: config.deviceInfo.deviceId,
|
|
48
|
+
port: config.deviceInfo.port,
|
|
49
|
+
},
|
|
50
|
+
onStatusEvent: this.handleStatusEvent,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
this.cloudClient.setMessageHandler(this.messageHandler.handleCloudMessage);
|
|
55
|
+
this.cloudClient.setOpenHandler(this.handleCloudOpen);
|
|
56
|
+
this.cloudClient.setCloseHandler(this.handleCloudClose);
|
|
57
|
+
this.cloudClient.setRemoteDeviceOfflineHandler(this.handleRemoteDeviceOffline);
|
|
58
|
+
this.cloudClient.setDeviceNotRegisteredHandler(this.handleDeviceNotRegistered);
|
|
59
|
+
|
|
60
|
+
// 实例化AdminGatewayClient
|
|
61
|
+
this.adminClientManager.init();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
start(): void {
|
|
65
|
+
useClawLogger().info("[yoyoclaw-channel] starting connection");
|
|
66
|
+
this.adminClientManager.ensureConnected();
|
|
67
|
+
this.cloudClient.connect();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 关闭连接
|
|
72
|
+
*/
|
|
73
|
+
destroy(): void {
|
|
74
|
+
useClawLogger().info("[yoyoclaw-channel] closing connection");
|
|
75
|
+
this.sessionManager.closeAllNodeGatewayClients();
|
|
76
|
+
this.adminClientManager.destroy();
|
|
77
|
+
this.cloudClient.close();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 处理云侧连接打开
|
|
82
|
+
*/
|
|
83
|
+
private handleCloudOpen = () => {
|
|
84
|
+
useClawLogger().info("[yoyoclaw-channel] cloud connection established");
|
|
85
|
+
this.config.onOpen?.();
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 统一处理所有状态事件
|
|
90
|
+
*/
|
|
91
|
+
private handleStatusEvent = (event: any) => {
|
|
92
|
+
this.config.onStatusEvent?.(event);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 处理云侧连接关闭
|
|
97
|
+
*/
|
|
98
|
+
private handleCloudClose = () => {
|
|
99
|
+
useClawLogger().info("[yoyoclaw-channel] cloud connection closed");
|
|
100
|
+
this.config.onClose?.();
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 处理对向设备离线
|
|
105
|
+
*/
|
|
106
|
+
private handleRemoteDeviceOffline = (sourceDeviceId: string) => {
|
|
107
|
+
this.sessionManager.closeNodeGatewayClient(sourceDeviceId);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 处理当前设备未注册
|
|
112
|
+
*/
|
|
113
|
+
private handleDeviceNotRegistered = () => {
|
|
114
|
+
useClawLogger().info("[yoyoclaw-channel] device not registered, notifying connection layer");
|
|
115
|
+
this.config.onDeviceNotRegistered?.();
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -126,12 +126,12 @@ export class ClawCloudSocketClient {
|
|
|
126
126
|
|
|
127
127
|
this.ws.on("ping", () => {
|
|
128
128
|
// 收到服务端的 ping,自动回复 pong(ws 库会自动处理)
|
|
129
|
-
useClawLogger().debug("[claw-cloud-socket] received ping from server");
|
|
129
|
+
useClawLogger().debug?.("[claw-cloud-socket] received ping from server");
|
|
130
130
|
});
|
|
131
131
|
|
|
132
132
|
this.ws.on("pong", () => {
|
|
133
133
|
// 收到服务端的 pong 响应
|
|
134
|
-
useClawLogger().debug("[claw-cloud-socket] received pong from server");
|
|
134
|
+
useClawLogger().debug?.("[claw-cloud-socket] received pong from server");
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
this.ws.on("close", (code: number, reason: Buffer) => {
|
|
@@ -354,7 +354,7 @@ export class ClawCloudSocketClient {
|
|
|
354
354
|
|
|
355
355
|
// 发送 ping
|
|
356
356
|
this.ws.ping();
|
|
357
|
-
useClawLogger().debug("[claw-cloud-socket] sent ping to server");
|
|
357
|
+
useClawLogger().debug?.("[claw-cloud-socket] sent ping to server");
|
|
358
358
|
}, PING_INTERVAL);
|
|
359
359
|
}
|
|
360
360
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gateway Channel 导出
|
|
3
|
-
*/
|
|
4
|
-
export { ClawChannel } from "./channel.js";
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Channel 导出
|
|
3
|
+
*/
|
|
4
|
+
export { ClawChannel } from "./channel.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { YoyoClawMessage, DeviceSessionInfo } from "./types.js";
|
|
2
|
-
import type { ClawCloudSocketClient } from "./client.js";
|
|
3
|
-
import { SessionManager } from "./session-manager.js";
|
|
4
|
-
import { AdminClientManager } from "./admin-client-manager.js";
|
|
5
1
|
import type { NodeStatusEvent } from "../gateway-client/node-gateway-client.js";
|
|
6
2
|
import { useClawLogger } from "../utils/logger.js";
|
|
3
|
+
import { AdminClientManager } from "./admin-client-manager.js";
|
|
4
|
+
import type { ClawCloudSocketClient } from "./client.js";
|
|
5
|
+
import { SessionManager } from "./session-manager.js";
|
|
6
|
+
import type { YoyoClawMessage, DeviceSessionInfo } from "./types.js";
|
|
7
7
|
|
|
8
8
|
export interface MessageHandlerConfig {
|
|
9
9
|
deviceInfo: { deviceId: string; port: number };
|
|
@@ -60,30 +60,29 @@ export class MessageHandler {
|
|
|
60
60
|
* 处理配对消息,创建GatewayClient连接
|
|
61
61
|
*/
|
|
62
62
|
private handlePairMessage(message: YoyoClawMessage): void {
|
|
63
|
-
if (message.msgType !== "devicePairMessage")
|
|
63
|
+
if (message.msgType !== "devicePairMessage") {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
64
66
|
|
|
65
67
|
try {
|
|
66
68
|
const { sourceDeviceId, sourceDeviceInfo, targetDeviceId, port, sessionInfo } = message;
|
|
67
69
|
|
|
68
|
-
if (
|
|
69
|
-
sourceDeviceId &&
|
|
70
|
-
targetDeviceId &&
|
|
71
|
-
port &&
|
|
72
|
-
sourceDeviceInfo?.deviceId
|
|
73
|
-
) {
|
|
70
|
+
if (sourceDeviceId && targetDeviceId && port && sourceDeviceInfo?.deviceId) {
|
|
74
71
|
const hardwareDeviceId = sourceDeviceInfo.deviceId;
|
|
75
72
|
const newTimestamp = sessionInfo?.nodeConnectTimestamp;
|
|
76
73
|
|
|
77
74
|
if (!newTimestamp) {
|
|
78
75
|
// 兜底旧版本,异常场景,暂时不移除旧连接
|
|
79
|
-
useClawLogger().warn(
|
|
76
|
+
useClawLogger().warn(
|
|
77
|
+
`[yoyoclaw-channel] pair message missing timestamp for device: ${sourceDeviceId}`,
|
|
78
|
+
);
|
|
80
79
|
} else {
|
|
81
80
|
// 关闭该硬件设备ID对应的所有前序 GatewayClient(timestamp 小于新 timestamp)
|
|
82
81
|
this.sessionManager.closePreviousNodeGatewayClients(hardwareDeviceId, newTimestamp);
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
useClawLogger().info(
|
|
86
|
-
`[yoyoclaw-channel] received pair message, creating node gateway client for device: ${sourceDeviceId}, hardware device: ${hardwareDeviceId}, timestamp: ${newTimestamp}
|
|
85
|
+
`[yoyoclaw-channel] received pair message, creating node gateway client for device: ${sourceDeviceId}, hardware device: ${hardwareDeviceId}, timestamp: ${newTimestamp}`,
|
|
87
86
|
);
|
|
88
87
|
|
|
89
88
|
const sessionInfoData: DeviceSessionInfo = {
|
|
@@ -122,9 +121,10 @@ export class MessageHandler {
|
|
|
122
121
|
onStatusEvent: (event: NodeStatusEvent) => {
|
|
123
122
|
// 通知状态跟踪器:GatewayClient状态变化
|
|
124
123
|
this.config.onStatusEvent?.({
|
|
125
|
-
type:
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
type:
|
|
125
|
+
event.type === "node_connected"
|
|
126
|
+
? "gateway_client_connected"
|
|
127
|
+
: "gateway_client_disconnected",
|
|
128
128
|
timestamp: event.timestamp,
|
|
129
129
|
data: event.data,
|
|
130
130
|
});
|
|
@@ -134,9 +134,7 @@ export class MessageHandler {
|
|
|
134
134
|
nodeGatewayClient.connect();
|
|
135
135
|
}
|
|
136
136
|
} catch (error) {
|
|
137
|
-
useClawLogger().error(
|
|
138
|
-
`[yoyoclaw-channel] failed to handle pair message: ${String(error)}`
|
|
139
|
-
);
|
|
137
|
+
useClawLogger().error(`[yoyoclaw-channel] failed to handle pair message: ${String(error)}`);
|
|
140
138
|
}
|
|
141
139
|
}
|
|
142
140
|
|
|
@@ -156,20 +154,20 @@ export class MessageHandler {
|
|
|
156
154
|
const nodeGatewayClient = this.sessionManager.getNodeGatewayClient(sourceDeviceId);
|
|
157
155
|
if (!nodeGatewayClient) {
|
|
158
156
|
useClawLogger().warn(
|
|
159
|
-
`[yoyoclaw-channel] no node gateway client found for source device: ${hardwareDeviceId}, session: ${sourceDeviceId}
|
|
157
|
+
`[yoyoclaw-channel] no node gateway client found for source device: ${hardwareDeviceId}, session: ${sourceDeviceId}`,
|
|
160
158
|
);
|
|
161
159
|
return;
|
|
162
160
|
}
|
|
163
161
|
|
|
164
162
|
if (message.data) {
|
|
165
163
|
useClawLogger().info(
|
|
166
|
-
`[yoyoclaw-channel] forwarding user message to node gateway from ${hardwareDeviceId}, session: ${sourceDeviceId}
|
|
164
|
+
`[yoyoclaw-channel] forwarding user message to node gateway from ${hardwareDeviceId}, session: ${sourceDeviceId}`,
|
|
167
165
|
);
|
|
168
166
|
nodeGatewayClient.send(message.data);
|
|
169
167
|
}
|
|
170
168
|
} catch (error) {
|
|
171
169
|
useClawLogger().error(
|
|
172
|
-
`[yoyoclaw-channel] failed to send node gateway message to ${hardwareDeviceId}: ${String(error)}, session: ${sourceDeviceId}
|
|
170
|
+
`[yoyoclaw-channel] failed to send node gateway message to ${hardwareDeviceId}: ${String(error)}, session: ${sourceDeviceId}`,
|
|
173
171
|
);
|
|
174
172
|
}
|
|
175
173
|
}
|
|
@@ -180,7 +178,9 @@ export class MessageHandler {
|
|
|
180
178
|
handleNodeGatewayMessage = (sourceDeviceId: string, data: string): void => {
|
|
181
179
|
const hardwareDeviceId = this.sessionManager.getHardwareDeviceId(sourceDeviceId);
|
|
182
180
|
if (!hardwareDeviceId) {
|
|
183
|
-
useClawLogger().warn(
|
|
181
|
+
useClawLogger().warn(
|
|
182
|
+
`[yoyoclaw-channel] node gateway source offline, session: ${sourceDeviceId}`,
|
|
183
|
+
);
|
|
184
184
|
return;
|
|
185
185
|
}
|
|
186
186
|
|
|
@@ -188,29 +188,36 @@ export class MessageHandler {
|
|
|
188
188
|
const deviceId = sessionInfo?.sourceInfo.sourceDeviceInfo?.deviceId;
|
|
189
189
|
|
|
190
190
|
if (!sessionInfo) {
|
|
191
|
-
useClawLogger().warn(
|
|
191
|
+
useClawLogger().warn(
|
|
192
|
+
`[yoyoclaw-channel] node gateway source offline, session: ${sourceDeviceId}`,
|
|
193
|
+
);
|
|
192
194
|
return;
|
|
193
195
|
}
|
|
194
196
|
|
|
195
|
-
useClawLogger().
|
|
196
|
-
`[yoyoclaw-channel] received node gateway message from ${deviceId} to cloud:, ${data.slice(0, 1000)}`
|
|
197
|
-
);
|
|
197
|
+
useClawLogger().info(`[yoyoclaw-channel] received node gateway message from ${deviceId}`);
|
|
198
198
|
|
|
199
199
|
try {
|
|
200
200
|
// 使用当前接收到的socket对应deviceId的来源信息
|
|
201
201
|
const targetDeviceId = sessionInfo.sourceInfo.sourceDeviceId;
|
|
202
|
+
|
|
203
|
+
useClawLogger().debug?.(
|
|
204
|
+
`[yoyoclaw-channel] trans gateway msg to cloud device: ${targetDeviceId}, ${data.slice(0, 1000)}`,
|
|
205
|
+
);
|
|
206
|
+
|
|
202
207
|
const result = this.sendMessage("userMessage", targetDeviceId, data, undefined, deviceId);
|
|
203
208
|
|
|
204
209
|
if (!result) {
|
|
205
210
|
// 云socket挂了,这个gateway连接就需要取消掉
|
|
206
211
|
// 最好不要一次性把所有的gateway连接都干掉,让惰性关闭
|
|
207
212
|
useClawLogger().error(
|
|
208
|
-
`[yoyoclaw-channel] failed to send message, cloud socket closed, from ${targetDeviceId}
|
|
213
|
+
`[yoyoclaw-channel] failed to send message, cloud socket closed, from ${targetDeviceId}`,
|
|
209
214
|
);
|
|
210
215
|
this.sessionManager.closeNodeGatewayClient(targetDeviceId);
|
|
211
216
|
}
|
|
212
217
|
} catch (error) {
|
|
213
|
-
useClawLogger().error(
|
|
218
|
+
useClawLogger().error(
|
|
219
|
+
`[yoyoclaw-channel] failed to handle node gateway message: ${String(error)}`,
|
|
220
|
+
);
|
|
214
221
|
}
|
|
215
222
|
};
|
|
216
223
|
|
|
@@ -227,7 +234,7 @@ export class MessageHandler {
|
|
|
227
234
|
return;
|
|
228
235
|
}
|
|
229
236
|
|
|
230
|
-
if (!await this.adminClientManager.waitForReady()) {
|
|
237
|
+
if (!(await this.adminClientManager.waitForReady())) {
|
|
231
238
|
useClawLogger().error("[yoyoclaw-channel] admin gateway client not ready after retry");
|
|
232
239
|
this.sendResponse("updateContexts", message.sourceDeviceId, {
|
|
233
240
|
success: false,
|
|
@@ -276,7 +283,7 @@ export class MessageHandler {
|
|
|
276
283
|
private async handleFetchContexts(message: YoyoClawMessage): Promise<void> {
|
|
277
284
|
useClawLogger().info("[yoyoclaw-channel] handling fetchContexts message");
|
|
278
285
|
|
|
279
|
-
if (!await this.adminClientManager.waitForReady()) {
|
|
286
|
+
if (!(await this.adminClientManager.waitForReady())) {
|
|
280
287
|
useClawLogger().error("[yoyoclaw-channel] admin gateway client not ready after retry");
|
|
281
288
|
this.sendResponse("fetchContexts", message.sourceDeviceId, {
|
|
282
289
|
success: false,
|
|
@@ -288,17 +295,18 @@ export class MessageHandler {
|
|
|
288
295
|
try {
|
|
289
296
|
const context = message.contexts?.[0];
|
|
290
297
|
const client = this.adminClientManager.getClient()!;
|
|
291
|
-
const { name } = context
|
|
298
|
+
const { name } = context?.header || {};
|
|
292
299
|
if (name === "skills") {
|
|
293
300
|
const result = await client.getSkillsStatus();
|
|
294
|
-
const skills =
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
301
|
+
const skills =
|
|
302
|
+
result.skills
|
|
303
|
+
?.filter((v) => v.eligible)
|
|
304
|
+
.map((v) => ({
|
|
305
|
+
name: v.name,
|
|
306
|
+
description: v.description,
|
|
307
|
+
source: v.source,
|
|
308
|
+
disableModelInvocation: v.disabled,
|
|
309
|
+
})) ?? [];
|
|
302
310
|
this.sendResponse("fetchContexts", message.sourceDeviceId, { success: true }, [
|
|
303
311
|
{ header: { name: "skills", namespace: "yoyoclaw" }, payload: { skills } },
|
|
304
312
|
]);
|
|
@@ -324,7 +332,7 @@ export class MessageHandler {
|
|
|
324
332
|
targetDeviceId: string,
|
|
325
333
|
data: string | Record<string, any>,
|
|
326
334
|
contexts?: YoyoClawMessage["contexts"],
|
|
327
|
-
logDeviceId?: string
|
|
335
|
+
logDeviceId?: string,
|
|
328
336
|
): boolean {
|
|
329
337
|
const message: YoyoClawMessage = {
|
|
330
338
|
msgType,
|
|
@@ -343,7 +351,7 @@ export class MessageHandler {
|
|
|
343
351
|
msgType: "updateContexts" | "fetchContexts",
|
|
344
352
|
targetDeviceId: string,
|
|
345
353
|
data: Record<string, any>,
|
|
346
|
-
contexts?: YoyoClawMessage["contexts"]
|
|
354
|
+
contexts?: YoyoClawMessage["contexts"],
|
|
347
355
|
): void {
|
|
348
356
|
this.sendMessage(msgType, targetDeviceId, data, contexts);
|
|
349
357
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ClawDeviceInfo } from "src/types.js";
|
|
2
2
|
import { NodeGatewayClient, type NodeStatusEvent } from "../gateway-client/node-gateway-client.js";
|
|
3
3
|
import { useClawLogger } from "../utils/logger.js";
|
|
4
|
+
import type { DeviceSessionInfo } from "./types.js";
|
|
4
5
|
|
|
5
6
|
export interface CreateNodeGatewayClientOptions {
|
|
6
7
|
sessionId: string;
|
|
7
8
|
hardwareDeviceId: string;
|
|
8
|
-
deviceInfo:
|
|
9
|
+
deviceInfo: ClawDeviceInfo;
|
|
9
10
|
onMessage: (data: string) => void;
|
|
10
11
|
onStatusEvent: (event: NodeStatusEvent) => void;
|
|
11
12
|
}
|
|
@@ -42,7 +43,9 @@ export class SessionManager {
|
|
|
42
43
|
|
|
43
44
|
getSession(sessionId: string): DeviceSessionInfo | undefined {
|
|
44
45
|
const hardwareDeviceId = this.sessionIdToHardwareDeviceMap.get(sessionId);
|
|
45
|
-
if (!hardwareDeviceId)
|
|
46
|
+
if (!hardwareDeviceId) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
46
49
|
const sessions = this.deviceSessionsMap.get(hardwareDeviceId);
|
|
47
50
|
return sessions?.find((s) => s.sessionId === sessionId);
|
|
48
51
|
}
|
|
@@ -82,24 +85,26 @@ export class SessionManager {
|
|
|
82
85
|
this.nodeGatewayClientsMap.delete(sessionId);
|
|
83
86
|
this.removeSession(sessionId);
|
|
84
87
|
useClawLogger().info(
|
|
85
|
-
`[yoyoclaw-channel] closed node gateway client for session: ${sessionId}
|
|
88
|
+
`[yoyoclaw-channel] closed node gateway client for session: ${sessionId}`,
|
|
86
89
|
);
|
|
87
90
|
}
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
/**
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
* 关闭硬件设备的所有前序 GatewayClient(timestamp 小于指定值)
|
|
95
|
+
*/
|
|
93
96
|
closePreviousNodeGatewayClients(hardwareDeviceId: string, newTimestamp: number): void {
|
|
94
97
|
const sessions = this.deviceSessionsMap.get(hardwareDeviceId);
|
|
95
|
-
if (!sessions || sessions.length === 0)
|
|
98
|
+
if (!sessions || sessions.length === 0) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
96
101
|
|
|
97
102
|
// 找出所有 timestamp 小于新 timestamp 的会话
|
|
98
103
|
const previousSessions = sessions.filter((s) => s.timestamp < newTimestamp);
|
|
99
104
|
|
|
100
105
|
if (previousSessions.length > 0) {
|
|
101
106
|
useClawLogger().info(
|
|
102
|
-
`[yoyoclaw-channel] closing ${previousSessions.length} previous node gateway client(s) for hardware device: ${hardwareDeviceId}, new timestamp: ${newTimestamp}
|
|
107
|
+
`[yoyoclaw-channel] closing ${previousSessions.length} previous node gateway client(s) for hardware device: ${hardwareDeviceId}, new timestamp: ${newTimestamp}`,
|
|
103
108
|
);
|
|
104
109
|
for (const session of previousSessions) {
|
|
105
110
|
this.closeNodeGatewayClient(session.sessionId);
|
|
@@ -114,7 +119,7 @@ export class SessionManager {
|
|
|
114
119
|
for (const [sessionId, client] of this.nodeGatewayClientsMap.entries()) {
|
|
115
120
|
client.stop();
|
|
116
121
|
useClawLogger().info(
|
|
117
|
-
`[yoyoclaw-channel] closed node gateway client for session: ${sessionId}
|
|
122
|
+
`[yoyoclaw-channel] closed node gateway client for session: ${sessionId}`,
|
|
118
123
|
);
|
|
119
124
|
}
|
|
120
125
|
this.nodeGatewayClientsMap.clear();
|