@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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/bin/remote-cli-router.js +2 -0
  4. package/dist/binding/BindingManager.d.ts +62 -0
  5. package/dist/binding/BindingManager.d.ts.map +1 -0
  6. package/dist/binding/BindingManager.js +119 -0
  7. package/dist/binding/BindingManager.js.map +1 -0
  8. package/dist/cli.d.ts +3 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +32 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/config.d.ts +19 -0
  13. package/dist/commands/config.d.ts.map +1 -0
  14. package/dist/commands/config.js +206 -0
  15. package/dist/commands/config.js.map +1 -0
  16. package/dist/commands/start.d.ts +5 -0
  17. package/dist/commands/start.d.ts.map +1 -0
  18. package/dist/commands/start.js +65 -0
  19. package/dist/commands/start.js.map +1 -0
  20. package/dist/commands/status.d.ts +5 -0
  21. package/dist/commands/status.d.ts.map +1 -0
  22. package/dist/commands/status.js +103 -0
  23. package/dist/commands/status.js.map +1 -0
  24. package/dist/commands/stop.d.ts +5 -0
  25. package/dist/commands/stop.d.ts.map +1 -0
  26. package/dist/commands/stop.js +56 -0
  27. package/dist/commands/stop.js.map +1 -0
  28. package/dist/config/ConfigManager.d.ts +46 -0
  29. package/dist/config/ConfigManager.d.ts.map +1 -0
  30. package/dist/config/ConfigManager.js +101 -0
  31. package/dist/config/ConfigManager.js.map +1 -0
  32. package/dist/feishu/FeishuClient.d.ts +46 -0
  33. package/dist/feishu/FeishuClient.d.ts.map +1 -0
  34. package/dist/feishu/FeishuClient.js +130 -0
  35. package/dist/feishu/FeishuClient.js.map +1 -0
  36. package/dist/feishu/FeishuLongConnHandler.d.ts +149 -0
  37. package/dist/feishu/FeishuLongConnHandler.d.ts.map +1 -0
  38. package/dist/feishu/FeishuLongConnHandler.js +632 -0
  39. package/dist/feishu/FeishuLongConnHandler.js.map +1 -0
  40. package/dist/server.d.ts +80 -0
  41. package/dist/server.d.ts.map +1 -0
  42. package/dist/server.js +533 -0
  43. package/dist/server.js.map +1 -0
  44. package/dist/storage/JsonStore.d.ts +90 -0
  45. package/dist/storage/JsonStore.d.ts.map +1 -0
  46. package/dist/storage/JsonStore.js +215 -0
  47. package/dist/storage/JsonStore.js.map +1 -0
  48. package/dist/storage/MemoryStore.d.ts +69 -0
  49. package/dist/storage/MemoryStore.d.ts.map +1 -0
  50. package/dist/storage/MemoryStore.js +117 -0
  51. package/dist/storage/MemoryStore.js.map +1 -0
  52. package/dist/types/config.d.ts +53 -0
  53. package/dist/types/config.d.ts.map +1 -0
  54. package/dist/types/config.js +31 -0
  55. package/dist/types/config.js.map +1 -0
  56. package/dist/types/index.d.ts +93 -0
  57. package/dist/types/index.d.ts.map +1 -0
  58. package/dist/types/index.js +18 -0
  59. package/dist/types/index.js.map +1 -0
  60. package/dist/utils/PidManager.d.ts +28 -0
  61. package/dist/utils/PidManager.d.ts.map +1 -0
  62. package/dist/utils/PidManager.js +90 -0
  63. package/dist/utils/PidManager.js.map +1 -0
  64. package/dist/utils/ToolFormatter.d.ts +41 -0
  65. package/dist/utils/ToolFormatter.d.ts.map +1 -0
  66. package/dist/utils/ToolFormatter.js +273 -0
  67. package/dist/utils/ToolFormatter.js.map +1 -0
  68. package/dist/websocket/ConnectionHub.d.ts +73 -0
  69. package/dist/websocket/ConnectionHub.d.ts.map +1 -0
  70. package/dist/websocket/ConnectionHub.js +177 -0
  71. package/dist/websocket/ConnectionHub.js.map +1 -0
  72. 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
+ }