@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,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startCommand = startCommand;
|
|
4
|
+
const ConfigManager_1 = require("../config/ConfigManager");
|
|
5
|
+
const JsonStore_1 = require("../storage/JsonStore");
|
|
6
|
+
const server_1 = require("../server");
|
|
7
|
+
const PidManager_1 = require("../utils/PidManager");
|
|
8
|
+
/**
|
|
9
|
+
* Start the router server
|
|
10
|
+
*/
|
|
11
|
+
async function startCommand() {
|
|
12
|
+
try {
|
|
13
|
+
console.log('\nš Starting remote CLI router server...\n');
|
|
14
|
+
// Check if server is already running
|
|
15
|
+
const pidManager = new PidManager_1.PidManager();
|
|
16
|
+
const runningPid = await pidManager.getRunningPid();
|
|
17
|
+
if (runningPid) {
|
|
18
|
+
console.error(`ā Router server is already running (PID: ${runningPid})`);
|
|
19
|
+
console.error('\nUse one of these commands:');
|
|
20
|
+
console.error(' remote-cli-router stop - Stop the server');
|
|
21
|
+
console.error(' remote-cli-router status - Check server status\n');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
// Load configuration
|
|
25
|
+
const config = await ConfigManager_1.ConfigManager.initialize();
|
|
26
|
+
// Validate required configuration
|
|
27
|
+
const appId = config.get('feishu', 'appId');
|
|
28
|
+
const appSecret = config.get('feishu', 'appSecret');
|
|
29
|
+
if (!appId || !appSecret) {
|
|
30
|
+
console.error('ā Missing required configuration!');
|
|
31
|
+
console.error('\nPlease run configuration first:');
|
|
32
|
+
console.error(' remote-cli-router config\n');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
// Write PID file
|
|
36
|
+
await pidManager.writePid(process.pid);
|
|
37
|
+
// Initialize storage
|
|
38
|
+
const store = new JsonStore_1.JsonStore();
|
|
39
|
+
await store.initialize();
|
|
40
|
+
// Create and start server
|
|
41
|
+
const server = new server_1.RouterServer(config, store);
|
|
42
|
+
await server.start();
|
|
43
|
+
// Handle graceful shutdown
|
|
44
|
+
const shutdown = async (signal) => {
|
|
45
|
+
console.log(`\n\nReceived ${signal}, shutting down gracefully...`);
|
|
46
|
+
try {
|
|
47
|
+
await server.stop();
|
|
48
|
+
await pidManager.removePid();
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error('Error during shutdown:', error);
|
|
53
|
+
await pidManager.removePid();
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
58
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error('ā Failed to start router server:', error.message);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":";;AAQA,oCA6DC;AArED,2DAAwD;AACxD,oDAAiD;AACjD,sCAAyC;AACzC,oDAAiD;AAEjD;;GAEG;AACI,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAE3D,qCAAqC;QACrC,MAAM,UAAU,GAAG,IAAI,uBAAU,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,aAAa,EAAE,CAAC;QACpD,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,4CAA4C,UAAU,GAAG,CAAC,CAAC;YACzE,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAC9C,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;YAC/D,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,qBAAqB;QACrB,MAAM,MAAM,GAAG,MAAM,6BAAa,CAAC,UAAU,EAAE,CAAC;QAEhD,kCAAkC;QAClC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAEpD,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACnD,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACnD,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,iBAAiB;QACjB,MAAM,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAEvC,qBAAqB;QACrB,MAAM,KAAK,GAAG,IAAI,qBAAS,EAAE,CAAC;QAC9B,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QAEzB,0BAA0B;QAC1B,MAAM,MAAM,GAAG,IAAI,qBAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC/C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QAErB,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;YACxC,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,+BAA+B,CAAC,CAAC;YACnE,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBACpB,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC;gBAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;gBAC/C,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC;gBAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEjD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAqEnD"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.statusCommand = statusCommand;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const ConfigManager_1 = require("../config/ConfigManager");
|
|
9
|
+
const PidManager_1 = require("../utils/PidManager");
|
|
10
|
+
/**
|
|
11
|
+
* Show router server status
|
|
12
|
+
*/
|
|
13
|
+
async function statusCommand() {
|
|
14
|
+
try {
|
|
15
|
+
console.log('\nš Router Server Status\n');
|
|
16
|
+
console.log('ā'.repeat(50));
|
|
17
|
+
const pidManager = new PidManager_1.PidManager();
|
|
18
|
+
const runningPid = await pidManager.getRunningPid();
|
|
19
|
+
if (!runningPid) {
|
|
20
|
+
console.log('Status: ā Not Running');
|
|
21
|
+
console.log('\nUse this command to start:');
|
|
22
|
+
console.log(' remote-cli-router start\n');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log(`Status: ā
Running`);
|
|
26
|
+
console.log(`PID: ${runningPid}`);
|
|
27
|
+
// Try to load configuration and get health status
|
|
28
|
+
try {
|
|
29
|
+
const config = await ConfigManager_1.ConfigManager.initialize();
|
|
30
|
+
const host = config.get('server', 'host');
|
|
31
|
+
const port = config.get('server', 'port');
|
|
32
|
+
console.log(`Host: ${host}`);
|
|
33
|
+
console.log(`Port: ${port}`);
|
|
34
|
+
// Try to fetch health status
|
|
35
|
+
const healthUrl = `http://localhost:${port}/health`;
|
|
36
|
+
try {
|
|
37
|
+
const response = await axios_1.default.get(healthUrl, { timeout: 3000 });
|
|
38
|
+
const health = response.data;
|
|
39
|
+
console.log(`Connections: ${health.connections || 0}`);
|
|
40
|
+
console.log(`Devices: ${health.devices?.length || 0}`);
|
|
41
|
+
if (health.devices && health.devices.length > 0) {
|
|
42
|
+
console.log('\nConnected Devices:');
|
|
43
|
+
health.devices.forEach((deviceId, index) => {
|
|
44
|
+
console.log(` ${index + 1}. ${deviceId}`);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
console.log(`\nUptime: ${formatUptime(Date.now() - health.timestamp)}`);
|
|
48
|
+
}
|
|
49
|
+
catch (healthError) {
|
|
50
|
+
console.log('\nā ļø Could not fetch health status');
|
|
51
|
+
console.log(` API endpoint (${healthUrl}) is not responding`);
|
|
52
|
+
console.log(` The server process is running but may not be fully started`);
|
|
53
|
+
}
|
|
54
|
+
// Show configuration
|
|
55
|
+
console.log('\nConfiguration:');
|
|
56
|
+
const appId = config.get('feishu', 'appId');
|
|
57
|
+
console.log(` App ID: ${appId ? maskString(appId) : 'Not configured'}`);
|
|
58
|
+
console.log(` Environment: ${config.get('server', 'nodeEnv')}`);
|
|
59
|
+
}
|
|
60
|
+
catch (configError) {
|
|
61
|
+
console.log('\nā ļø Could not load configuration');
|
|
62
|
+
}
|
|
63
|
+
console.log('\n' + 'ā'.repeat(50));
|
|
64
|
+
console.log('\nAvailable commands:');
|
|
65
|
+
console.log(' remote-cli-router stop - Stop the server');
|
|
66
|
+
console.log(' remote-cli-router config - View/edit configuration\n');
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error('ā Failed to check status:', error.message);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Mask sensitive string (show first and last few characters)
|
|
75
|
+
*/
|
|
76
|
+
function maskString(str) {
|
|
77
|
+
if (str.length <= 8) {
|
|
78
|
+
return '***';
|
|
79
|
+
}
|
|
80
|
+
return `${str.substring(0, 4)}...${str.substring(str.length - 4)}`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Format uptime in human-readable format
|
|
84
|
+
*/
|
|
85
|
+
function formatUptime(ms) {
|
|
86
|
+
const seconds = Math.floor(ms / 1000);
|
|
87
|
+
const minutes = Math.floor(seconds / 60);
|
|
88
|
+
const hours = Math.floor(minutes / 60);
|
|
89
|
+
const days = Math.floor(hours / 24);
|
|
90
|
+
if (days > 0) {
|
|
91
|
+
return `${days}d ${hours % 24}h ${minutes % 60}m`;
|
|
92
|
+
}
|
|
93
|
+
else if (hours > 0) {
|
|
94
|
+
return `${hours}h ${minutes % 60}m`;
|
|
95
|
+
}
|
|
96
|
+
else if (minutes > 0) {
|
|
97
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return `${seconds}s`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAqDjD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stopCommand = stopCommand;
|
|
4
|
+
const PidManager_1 = require("../utils/PidManager");
|
|
5
|
+
/**
|
|
6
|
+
* Stop the router server
|
|
7
|
+
*/
|
|
8
|
+
async function stopCommand() {
|
|
9
|
+
console.log('\nš Stopping router server...\n');
|
|
10
|
+
const pidManager = new PidManager_1.PidManager();
|
|
11
|
+
try {
|
|
12
|
+
const runningPid = await pidManager.getRunningPid();
|
|
13
|
+
if (!runningPid) {
|
|
14
|
+
console.log('ā Router server is not running');
|
|
15
|
+
console.log('\nUse this command to start:');
|
|
16
|
+
console.log(' remote-cli-router start\n');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
console.log(`Found running server (PID: ${runningPid})`);
|
|
20
|
+
console.log('Sending shutdown signal...');
|
|
21
|
+
try {
|
|
22
|
+
// Send SIGTERM for graceful shutdown
|
|
23
|
+
process.kill(runningPid, 'SIGTERM');
|
|
24
|
+
// Wait for process to exit (max 10 seconds)
|
|
25
|
+
const maxWaitTime = 10000;
|
|
26
|
+
const startTime = Date.now();
|
|
27
|
+
while (pidManager.isProcessRunning(runningPid)) {
|
|
28
|
+
if (Date.now() - startTime > maxWaitTime) {
|
|
29
|
+
console.log('\nā ļø Process did not stop gracefully, sending SIGKILL...');
|
|
30
|
+
process.kill(runningPid, 'SIGKILL');
|
|
31
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
35
|
+
}
|
|
36
|
+
// Clean up PID file
|
|
37
|
+
await pidManager.removePid();
|
|
38
|
+
console.log('ā
Router server stopped successfully\n');
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error.code === 'ESRCH') {
|
|
42
|
+
// Process doesn't exist
|
|
43
|
+
await pidManager.removePid();
|
|
44
|
+
console.log('ā
Process already stopped, cleaned up PID file\n');
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.log(`ā Failed to stop router server: ${error.message}\n`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=stop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":";;AAKA,kCAqDC;AA1DD,oDAAiD;AAEjD;;GAEG;AACI,KAAK,UAAU,WAAW;IAC/B,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAEhD,MAAM,UAAU,GAAG,IAAI,uBAAU,EAAE,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,aAAa,EAAE,CAAC;QAEpD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,8BAA8B,UAAU,GAAG,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAE1C,IAAI,CAAC;YACH,qCAAqC;YACrC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;YAEpC,4CAA4C;YAC5C,MAAM,WAAW,GAAG,KAAK,CAAC;YAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAE7B,OAAO,UAAU,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/C,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,WAAW,EAAE,CAAC;oBACzC,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;oBACzE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;oBACpC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;oBACvD,MAAM;gBACR,CAAC;gBACD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YACzD,CAAC;YAED,oBAAoB;YACpB,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC;YAE7B,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC3B,wBAAwB;gBACxB,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC;gBAC7B,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;YAClE,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,mCAAmC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { RouterConfig } from '../types/config';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration manager for router server
|
|
4
|
+
*/
|
|
5
|
+
export declare class ConfigManager {
|
|
6
|
+
private config;
|
|
7
|
+
private configPath;
|
|
8
|
+
private static CONFIG_DIR;
|
|
9
|
+
private static CONFIG_FILE;
|
|
10
|
+
private constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Initialize configuration manager
|
|
13
|
+
*/
|
|
14
|
+
static initialize(): Promise<ConfigManager>;
|
|
15
|
+
/**
|
|
16
|
+
* Get configuration value
|
|
17
|
+
*/
|
|
18
|
+
get<K extends keyof RouterConfig>(key: K): RouterConfig[K];
|
|
19
|
+
get<K extends keyof RouterConfig, SK extends keyof RouterConfig[K]>(key: K, subKey: SK): RouterConfig[K][SK];
|
|
20
|
+
/**
|
|
21
|
+
* Set configuration value
|
|
22
|
+
*/
|
|
23
|
+
set<K extends keyof RouterConfig>(key: K, value: RouterConfig[K]): void;
|
|
24
|
+
set<K extends keyof RouterConfig, SK extends keyof RouterConfig[K]>(key: K, subKey: SK, value: RouterConfig[K][SK]): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get all configuration
|
|
27
|
+
*/
|
|
28
|
+
getAll(): RouterConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Check if Feishu is configured
|
|
31
|
+
*/
|
|
32
|
+
isFeishuConfigured(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Save configuration to disk
|
|
35
|
+
*/
|
|
36
|
+
save(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Get configuration file path
|
|
39
|
+
*/
|
|
40
|
+
getConfigPath(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Reset to default configuration
|
|
43
|
+
*/
|
|
44
|
+
reset(): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=ConfigManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigManager.d.ts","sourceRoot":"","sources":["../../src/config/ConfigManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAkB,MAAM,iBAAiB,CAAC;AAK/D;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAiD;IAC1E,OAAO,CAAC,MAAM,CAAC,WAAW,CAAiB;IAE3C,OAAO;IAKP;;OAEG;WACU,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC;IA0BjD;;OAEG;IACH,GAAG,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,GAAG,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IAC1D,GAAG,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,EAAE,SAAS,MAAM,YAAY,CAAC,CAAC,CAAC,EAChE,GAAG,EAAE,CAAC,EACN,MAAM,EAAE,EAAE,GACT,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAStB;;OAEG;IACH,GAAG,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IACvE,GAAG,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,EAAE,SAAS,MAAM,YAAY,CAAC,CAAC,CAAC,EAChE,GAAG,EAAE,CAAC,EACN,MAAM,EAAE,EAAE,EACV,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GACzB,IAAI;IAaP;;OAEG;IACH,MAAM,IAAI,YAAY;IAItB;;OAEG;IACH,kBAAkB,IAAI,OAAO;IAI7B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ConfigManager = void 0;
|
|
7
|
+
const config_1 = require("../types/config");
|
|
8
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
/**
|
|
12
|
+
* Configuration manager for router server
|
|
13
|
+
*/
|
|
14
|
+
class ConfigManager {
|
|
15
|
+
config;
|
|
16
|
+
configPath;
|
|
17
|
+
static CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.remote-cli-router');
|
|
18
|
+
static CONFIG_FILE = 'config.json';
|
|
19
|
+
constructor(config, configPath) {
|
|
20
|
+
this.config = config;
|
|
21
|
+
this.configPath = configPath;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Initialize configuration manager
|
|
25
|
+
*/
|
|
26
|
+
static async initialize() {
|
|
27
|
+
const configPath = path_1.default.join(ConfigManager.CONFIG_DIR, ConfigManager.CONFIG_FILE);
|
|
28
|
+
// Ensure config directory exists
|
|
29
|
+
await promises_1.default.mkdir(ConfigManager.CONFIG_DIR, { recursive: true });
|
|
30
|
+
let config;
|
|
31
|
+
try {
|
|
32
|
+
// Try to load existing config
|
|
33
|
+
const content = await promises_1.default.readFile(configPath, 'utf-8');
|
|
34
|
+
config = JSON.parse(content);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
// File doesn't exist or is invalid, use defaults
|
|
38
|
+
if (error.code === 'ENOENT') {
|
|
39
|
+
config = { ...config_1.DEFAULT_CONFIG };
|
|
40
|
+
// Save default config
|
|
41
|
+
await promises_1.default.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return new ConfigManager(config, configPath);
|
|
48
|
+
}
|
|
49
|
+
get(key, subKey) {
|
|
50
|
+
if (subKey !== undefined) {
|
|
51
|
+
const parent = this.config[key];
|
|
52
|
+
return parent ? parent[subKey] : undefined;
|
|
53
|
+
}
|
|
54
|
+
return this.config[key];
|
|
55
|
+
}
|
|
56
|
+
set(key, subKeyOrValue, value) {
|
|
57
|
+
if (value !== undefined && typeof subKeyOrValue === 'string') {
|
|
58
|
+
// Setting nested property
|
|
59
|
+
const parent = { ...this.config[key] };
|
|
60
|
+
parent[subKeyOrValue] = value;
|
|
61
|
+
this.config[key] = parent;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Setting top-level property
|
|
65
|
+
this.config[key] = subKeyOrValue;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get all configuration
|
|
70
|
+
*/
|
|
71
|
+
getAll() {
|
|
72
|
+
return { ...this.config };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if Feishu is configured
|
|
76
|
+
*/
|
|
77
|
+
isFeishuConfigured() {
|
|
78
|
+
return !!(this.config.feishu.appId && this.config.feishu.appSecret);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Save configuration to disk
|
|
82
|
+
*/
|
|
83
|
+
async save() {
|
|
84
|
+
await promises_1.default.writeFile(this.configPath, JSON.stringify(this.config, null, 2), 'utf-8');
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get configuration file path
|
|
88
|
+
*/
|
|
89
|
+
getConfigPath() {
|
|
90
|
+
return this.configPath;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Reset to default configuration
|
|
94
|
+
*/
|
|
95
|
+
async reset() {
|
|
96
|
+
this.config = { ...config_1.DEFAULT_CONFIG };
|
|
97
|
+
await this.save();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.ConfigManager = ConfigManager;
|
|
101
|
+
//# sourceMappingURL=ConfigManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigManager.js","sourceRoot":"","sources":["../../src/config/ConfigManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feishu API Client
|
|
3
|
+
* Responsible for interacting with Feishu API, sending messages and managing access tokens
|
|
4
|
+
*/
|
|
5
|
+
export declare class FeishuClient {
|
|
6
|
+
private appId;
|
|
7
|
+
private appSecret;
|
|
8
|
+
private axios;
|
|
9
|
+
private accessToken;
|
|
10
|
+
private tokenExpireTime;
|
|
11
|
+
constructor(appId: string, appSecret: string);
|
|
12
|
+
/**
|
|
13
|
+
* Get access token (with cache)
|
|
14
|
+
* @returns Access token
|
|
15
|
+
*/
|
|
16
|
+
getAccessToken(): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Send text message
|
|
19
|
+
* @param openId Feishu user open_id
|
|
20
|
+
* @param text Message text
|
|
21
|
+
* @returns Whether sending was successful
|
|
22
|
+
*/
|
|
23
|
+
sendTextMessage(openId: string, text: string): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Send Markdown message
|
|
26
|
+
* @param openId Feishu user open_id
|
|
27
|
+
* @param markdown Markdown content
|
|
28
|
+
* @returns Whether sending was successful
|
|
29
|
+
*/
|
|
30
|
+
sendMarkdownMessage(openId: string, markdown: string): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Send card message
|
|
33
|
+
* @param openId Feishu user open_id
|
|
34
|
+
* @param card Card content
|
|
35
|
+
* @returns Whether sending was successful
|
|
36
|
+
*/
|
|
37
|
+
sendCardMessage(openId: string, card: any): Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Reply to message
|
|
40
|
+
* @param messageId Message ID to reply to
|
|
41
|
+
* @param text Reply content
|
|
42
|
+
* @returns Whether sending was successful
|
|
43
|
+
*/
|
|
44
|
+
replyToMessage(messageId: string, text: string): Promise<boolean>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=FeishuClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeishuClient.d.ts","sourceRoot":"","sources":["../../src/feishu/FeishuClient.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,eAAe,CAAa;gBAExB,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAU5C;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAuBvC;;;;;OAKG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBrE;;;;;OAKG;IACG,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK7E;;;;;OAKG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBlE;;;;;OAKG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAqBxE"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.FeishuClient = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
/**
|
|
9
|
+
* Feishu API Client
|
|
10
|
+
* Responsible for interacting with Feishu API, sending messages and managing access tokens
|
|
11
|
+
*/
|
|
12
|
+
class FeishuClient {
|
|
13
|
+
appId;
|
|
14
|
+
appSecret;
|
|
15
|
+
axios;
|
|
16
|
+
accessToken = '';
|
|
17
|
+
tokenExpireTime = 0;
|
|
18
|
+
constructor(appId, appSecret) {
|
|
19
|
+
this.appId = appId;
|
|
20
|
+
this.appSecret = appSecret;
|
|
21
|
+
this.axios = axios_1.default.create({
|
|
22
|
+
baseURL: 'https://open.feishu.cn/open-apis',
|
|
23
|
+
timeout: 10000
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get access token (with cache)
|
|
28
|
+
* @returns Access token
|
|
29
|
+
*/
|
|
30
|
+
async getAccessToken() {
|
|
31
|
+
// If token exists and has not expired, return directly
|
|
32
|
+
if (this.accessToken && Date.now() < this.tokenExpireTime) {
|
|
33
|
+
return this.accessToken;
|
|
34
|
+
}
|
|
35
|
+
// Get new token
|
|
36
|
+
const response = await this.axios.post('/auth/v3/tenant_access_token/internal', {
|
|
37
|
+
app_id: this.appId,
|
|
38
|
+
app_secret: this.appSecret
|
|
39
|
+
});
|
|
40
|
+
if (response.data.code !== 0) {
|
|
41
|
+
throw new Error(`Failed to get access token: ${response.data.msg || 'Unknown error'}`);
|
|
42
|
+
}
|
|
43
|
+
this.accessToken = response.data.tenant_access_token;
|
|
44
|
+
// Token validity period, refresh 5 minutes early
|
|
45
|
+
this.tokenExpireTime = Date.now() + (response.data.expire - 300) * 1000;
|
|
46
|
+
return this.accessToken;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Send text message
|
|
50
|
+
* @param openId Feishu user open_id
|
|
51
|
+
* @param text Message text
|
|
52
|
+
* @returns Whether sending was successful
|
|
53
|
+
*/
|
|
54
|
+
async sendTextMessage(openId, text) {
|
|
55
|
+
try {
|
|
56
|
+
const token = await this.getAccessToken();
|
|
57
|
+
const response = await this.axios.post('/im/v1/messages', {
|
|
58
|
+
receive_id: openId,
|
|
59
|
+
msg_type: 'text',
|
|
60
|
+
content: JSON.stringify({ text })
|
|
61
|
+
}, {
|
|
62
|
+
params: { receive_id_type: 'open_id' },
|
|
63
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
64
|
+
});
|
|
65
|
+
return response.data.code === 0;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error('Failed to send text message:', error);
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Send Markdown message
|
|
74
|
+
* @param openId Feishu user open_id
|
|
75
|
+
* @param markdown Markdown content
|
|
76
|
+
* @returns Whether sending was successful
|
|
77
|
+
*/
|
|
78
|
+
async sendMarkdownMessage(openId, markdown) {
|
|
79
|
+
// Feishu text messages support partial Markdown, use text type directly
|
|
80
|
+
return this.sendTextMessage(openId, markdown);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Send card message
|
|
84
|
+
* @param openId Feishu user open_id
|
|
85
|
+
* @param card Card content
|
|
86
|
+
* @returns Whether sending was successful
|
|
87
|
+
*/
|
|
88
|
+
async sendCardMessage(openId, card) {
|
|
89
|
+
try {
|
|
90
|
+
const token = await this.getAccessToken();
|
|
91
|
+
const response = await this.axios.post('/im/v1/messages', {
|
|
92
|
+
receive_id: openId,
|
|
93
|
+
msg_type: 'interactive',
|
|
94
|
+
content: JSON.stringify(card)
|
|
95
|
+
}, {
|
|
96
|
+
params: { receive_id_type: 'open_id' },
|
|
97
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
98
|
+
});
|
|
99
|
+
return response.data.code === 0;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
console.error('Failed to send card message:', error);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Reply to message
|
|
108
|
+
* @param messageId Message ID to reply to
|
|
109
|
+
* @param text Reply content
|
|
110
|
+
* @returns Whether sending was successful
|
|
111
|
+
*/
|
|
112
|
+
async replyToMessage(messageId, text) {
|
|
113
|
+
try {
|
|
114
|
+
const token = await this.getAccessToken();
|
|
115
|
+
const response = await this.axios.post(`/im/v1/messages/${messageId}/reply`, {
|
|
116
|
+
msg_type: 'text',
|
|
117
|
+
content: JSON.stringify({ text })
|
|
118
|
+
}, {
|
|
119
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
120
|
+
});
|
|
121
|
+
return response.data.code === 0;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error('Failed to reply to message:', error);
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.FeishuClient = FeishuClient;
|
|
130
|
+
//# sourceMappingURL=FeishuClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeishuClient.js","sourceRoot":"","sources":["../../src/feishu/FeishuClient.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA6C;AAE7C;;;GAGG;AACH,MAAa,YAAY;IACf,KAAK,CAAS;IACd,SAAS,CAAS;IAClB,KAAK,CAAgB;IACrB,WAAW,GAAW,EAAE,CAAC;IACzB,eAAe,GAAW,CAAC,CAAC;IAEpC,YAAY,KAAa,EAAE,SAAiB;QAC1C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAE3B,IAAI,CAAC,KAAK,GAAG,eAAK,CAAC,MAAM,CAAC;YACxB,OAAO,EAAE,kCAAkC;YAC3C,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc;QAClB,uDAAuD;QACvD,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;QAED,gBAAgB;QAChB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,uCAAuC,EAAE;YAC9E,MAAM,EAAE,IAAI,CAAC,KAAK;YAClB,UAAU,EAAE,IAAI,CAAC,SAAS;SAC3B,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,eAAe,EAAE,CAAC,CAAC;QACzF,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,mBAAoB,CAAC;QACtD,iDAAiD;QACjD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC;QAExE,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,eAAe,CAAC,MAAc,EAAE,IAAY;QAChD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE1C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CACpC,iBAAiB,EACjB;gBACE,UAAU,EAAE,MAAM;gBAClB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;aAClC,EACD;gBACE,MAAM,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE;gBACtC,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;aAC9C,CACF,CAAC;YAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;YACrD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,mBAAmB,CAAC,MAAc,EAAE,QAAgB;QACxD,wEAAwE;QACxE,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,eAAe,CAAC,MAAc,EAAE,IAAS;QAC7C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE1C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CACpC,iBAAiB,EACjB;gBACE,UAAU,EAAE,MAAM;gBAClB,QAAQ,EAAE,aAAa;gBACvB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC9B,EACD;gBACE,MAAM,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE;gBACtC,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;aAC9C,CACF,CAAC;YAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;YACrD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,cAAc,CAAC,SAAiB,EAAE,IAAY;QAClD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAE1C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CACpC,mBAAmB,SAAS,QAAQ,EACpC;gBACE,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;aAClC,EACD;gBACE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;aAC9C,CACF,CAAC;YAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;YACpD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF;AA9ID,oCA8IC"}
|