@yu_robotics/remote-cli-router 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/bin/remote-cli-router.js +2 -0
- package/dist/binding/BindingManager.d.ts +62 -0
- package/dist/binding/BindingManager.d.ts.map +1 -0
- package/dist/binding/BindingManager.js +119 -0
- package/dist/binding/BindingManager.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +32 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +19 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +206 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/start.d.ts +5 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +65 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +103 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +5 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +56 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/config/ConfigManager.d.ts +46 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +101 -0
- package/dist/config/ConfigManager.js.map +1 -0
- package/dist/feishu/FeishuClient.d.ts +46 -0
- package/dist/feishu/FeishuClient.d.ts.map +1 -0
- package/dist/feishu/FeishuClient.js +130 -0
- package/dist/feishu/FeishuClient.js.map +1 -0
- package/dist/feishu/FeishuLongConnHandler.d.ts +149 -0
- package/dist/feishu/FeishuLongConnHandler.d.ts.map +1 -0
- package/dist/feishu/FeishuLongConnHandler.js +632 -0
- package/dist/feishu/FeishuLongConnHandler.js.map +1 -0
- package/dist/server.d.ts +80 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +533 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/JsonStore.d.ts +90 -0
- package/dist/storage/JsonStore.d.ts.map +1 -0
- package/dist/storage/JsonStore.js +215 -0
- package/dist/storage/JsonStore.js.map +1 -0
- package/dist/storage/MemoryStore.d.ts +69 -0
- package/dist/storage/MemoryStore.d.ts.map +1 -0
- package/dist/storage/MemoryStore.js +117 -0
- package/dist/storage/MemoryStore.js.map +1 -0
- package/dist/types/config.d.ts +53 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +31 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +93 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +18 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/PidManager.d.ts +28 -0
- package/dist/utils/PidManager.d.ts.map +1 -0
- package/dist/utils/PidManager.js +90 -0
- package/dist/utils/PidManager.js.map +1 -0
- package/dist/utils/ToolFormatter.d.ts +41 -0
- package/dist/utils/ToolFormatter.d.ts.map +1 -0
- package/dist/utils/ToolFormatter.js +273 -0
- package/dist/utils/ToolFormatter.js.map +1 -0
- package/dist/websocket/ConnectionHub.d.ts +73 -0
- package/dist/websocket/ConnectionHub.d.ts.map +1 -0
- package/dist/websocket/ConnectionHub.js +177 -0
- package/dist/websocket/ConnectionHub.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConnectionHub = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* WebSocket Connection Hub
|
|
6
|
+
* Manages all device WebSocket connections, responsible for message routing and connection management
|
|
7
|
+
*/
|
|
8
|
+
class ConnectionHub {
|
|
9
|
+
// Store deviceId -> WebSocket mapping
|
|
10
|
+
connections;
|
|
11
|
+
// Store deviceId -> last active time mapping
|
|
12
|
+
lastActiveMap;
|
|
13
|
+
constructor() {
|
|
14
|
+
this.connections = new Map();
|
|
15
|
+
this.lastActiveMap = new Map();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Register device connection
|
|
19
|
+
* @param deviceId Device unique identifier
|
|
20
|
+
* @param ws WebSocket connection
|
|
21
|
+
*/
|
|
22
|
+
registerConnection(deviceId, ws) {
|
|
23
|
+
// If device already has a connection, close the old connection first
|
|
24
|
+
if (this.connections.has(deviceId)) {
|
|
25
|
+
const oldWs = this.connections.get(deviceId);
|
|
26
|
+
try {
|
|
27
|
+
oldWs.close();
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
// Ignore close errors
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Register new connection
|
|
34
|
+
this.connections.set(deviceId, ws);
|
|
35
|
+
this.lastActiveMap.set(deviceId, Date.now());
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Unregister device connection
|
|
39
|
+
* @param deviceId Device unique identifier
|
|
40
|
+
*/
|
|
41
|
+
unregisterConnection(deviceId) {
|
|
42
|
+
this.connections.delete(deviceId);
|
|
43
|
+
this.lastActiveMap.delete(deviceId);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Send message to specified device
|
|
47
|
+
* @param deviceId Device unique identifier
|
|
48
|
+
* @param message Message object
|
|
49
|
+
* @returns Whether sending was successful
|
|
50
|
+
*/
|
|
51
|
+
async sendToDevice(deviceId, message) {
|
|
52
|
+
const ws = this.connections.get(deviceId);
|
|
53
|
+
if (!ws) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const messageStr = JSON.stringify(message);
|
|
58
|
+
ws.send(messageStr);
|
|
59
|
+
// Update last active time
|
|
60
|
+
this.lastActiveMap.set(deviceId, Date.now());
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
// Sending failed, connection may be disconnected
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if device is online
|
|
70
|
+
* @param deviceId Device unique identifier
|
|
71
|
+
* @returns Whether it is online
|
|
72
|
+
*/
|
|
73
|
+
isDeviceOnline(deviceId) {
|
|
74
|
+
return this.connections.has(deviceId);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get device last active time
|
|
78
|
+
* @param deviceId Device unique identifier
|
|
79
|
+
* @returns Last active timestamp, returns undefined if device does not exist
|
|
80
|
+
*/
|
|
81
|
+
getLastActiveTime(deviceId) {
|
|
82
|
+
return this.lastActiveMap.get(deviceId);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get list of all online device IDs
|
|
86
|
+
* @returns Device ID array
|
|
87
|
+
*/
|
|
88
|
+
getOnlineDevices() {
|
|
89
|
+
return Array.from(this.connections.keys());
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Update device last active time
|
|
93
|
+
* @param deviceId Device unique identifier
|
|
94
|
+
*/
|
|
95
|
+
updateLastActive(deviceId) {
|
|
96
|
+
if (this.connections.has(deviceId)) {
|
|
97
|
+
this.lastActiveMap.set(deviceId, Date.now());
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get connection statistics
|
|
102
|
+
* @returns Connection statistics
|
|
103
|
+
*/
|
|
104
|
+
getConnectionStats() {
|
|
105
|
+
const deviceIds = this.getOnlineDevices();
|
|
106
|
+
return {
|
|
107
|
+
totalConnections: deviceIds.length,
|
|
108
|
+
deviceIds
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Broadcast message to all devices
|
|
113
|
+
* @param message Message object
|
|
114
|
+
*/
|
|
115
|
+
async broadcast(message) {
|
|
116
|
+
const messageStr = JSON.stringify(message);
|
|
117
|
+
const promises = [];
|
|
118
|
+
for (const [deviceId, ws] of this.connections.entries()) {
|
|
119
|
+
const promise = new Promise((resolve) => {
|
|
120
|
+
try {
|
|
121
|
+
ws.send(messageStr);
|
|
122
|
+
this.lastActiveMap.set(deviceId, Date.now());
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
// Sending failed, ignore this device
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
resolve();
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
promises.push(promise);
|
|
132
|
+
}
|
|
133
|
+
await Promise.all(promises);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Clean up stale connections
|
|
137
|
+
* @param timeoutMs Timeout duration (milliseconds)
|
|
138
|
+
*/
|
|
139
|
+
cleanupStaleConnections(timeoutMs) {
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
const staleDevices = [];
|
|
142
|
+
for (const [deviceId, lastActive] of this.lastActiveMap.entries()) {
|
|
143
|
+
if (now - lastActive > timeoutMs) {
|
|
144
|
+
staleDevices.push(deviceId);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
for (const deviceId of staleDevices) {
|
|
148
|
+
const ws = this.connections.get(deviceId);
|
|
149
|
+
if (ws) {
|
|
150
|
+
try {
|
|
151
|
+
ws.close();
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
// Ignore close errors
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
this.unregisterConnection(deviceId);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Close all connections
|
|
162
|
+
*/
|
|
163
|
+
closeAllConnections() {
|
|
164
|
+
for (const ws of this.connections.values()) {
|
|
165
|
+
try {
|
|
166
|
+
ws.close();
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
// Ignore close errors
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
this.connections.clear();
|
|
173
|
+
this.lastActiveMap.clear();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
exports.ConnectionHub = ConnectionHub;
|
|
177
|
+
//# sourceMappingURL=ConnectionHub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConnectionHub.js","sourceRoot":"","sources":["../../src/websocket/ConnectionHub.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yu_robotics/remote-cli-router",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Router server for remote CLI - message forwarding between Feishu and local clients",
|
|
5
|
+
"main": "dist/cli.js",
|
|
6
|
+
"types": "dist/cli.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"remote-cli-router": "./bin/remote-cli-router.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"bin",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsx watch src/cli.ts -- start",
|
|
19
|
+
"start": "node dist/cli.js start",
|
|
20
|
+
"test": "vitest",
|
|
21
|
+
"test:coverage": "vitest --coverage",
|
|
22
|
+
"prepublishOnly": "npm run build && npm test"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/xiaoyu/remote-cli.git",
|
|
30
|
+
"directory": "packages/router"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/xiaoyu/remote-cli#readme",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/xiaoyu/remote-cli/issues"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"claude",
|
|
38
|
+
"cli",
|
|
39
|
+
"remote",
|
|
40
|
+
"feishu",
|
|
41
|
+
"router",
|
|
42
|
+
"websocket"
|
|
43
|
+
],
|
|
44
|
+
"author": "xiaoyu",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18.0.0"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@koa/router": "^12.0.1",
|
|
51
|
+
"@larksuiteoapi/node-sdk": "^1.59.0",
|
|
52
|
+
"axios": "^1.6.7",
|
|
53
|
+
"commander": "^12.0.0",
|
|
54
|
+
"dotenv": "^16.4.1",
|
|
55
|
+
"koa": "^2.15.0",
|
|
56
|
+
"koa-bodyparser": "^4.4.1",
|
|
57
|
+
"uuid": "^13.0.0",
|
|
58
|
+
"ws": "^8.18.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/koa": "^2.15.0",
|
|
62
|
+
"@types/koa__router": "^12.0.4",
|
|
63
|
+
"@types/koa-bodyparser": "^4.3.12",
|
|
64
|
+
"@types/uuid": "^10.0.0",
|
|
65
|
+
"@types/ws": "^8.5.10",
|
|
66
|
+
"@vitest/coverage-v8": "^1.2.0",
|
|
67
|
+
"tsx": "^4.7.0",
|
|
68
|
+
"vitest": "^1.2.0"
|
|
69
|
+
}
|
|
70
|
+
}
|