cursor-bridge 1.1.0 → 1.3.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 (3) hide show
  1. package/dist/index.js +101 -140
  2. package/package.json +2 -4
  3. package/src/index.ts +122 -194
package/dist/index.js CHANGED
@@ -4,44 +4,53 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- const ws_1 = require("ws");
8
- const uuid_1 = require("uuid");
7
+ const ws_1 = __importDefault(require("ws"));
8
+ const child_process_1 = require("child_process");
9
9
  const chalk_1 = __importDefault(require("chalk"));
10
- const os_1 = __importDefault(require("os"));
11
- const PORT = Number(process.argv[2]) || 9090;
12
- const TOKEN = (0, uuid_1.v4)();
13
- // 6 haneli pair code üret
10
+ const BRIDGE_URL = 'wss://cursor-226b2ae97542.herokuapp.com';
11
+ function sendToCursor(prompt) {
12
+ try {
13
+ // Escape special characters for AppleScript
14
+ const escaped = prompt
15
+ .replace(/\\/g, '\\\\')
16
+ .replace(/"/g, '\\"')
17
+ .replace(/\n/g, '\\n');
18
+ const script = `
19
+ tell application "Cursor"
20
+ activate
21
+ end tell
22
+ delay 0.5
23
+ tell application "System Events"
24
+ tell process "Cursor"
25
+ -- Open Composer with Cmd+I
26
+ keystroke "i" using command down
27
+ delay 0.3
28
+ -- Type the prompt
29
+ keystroke "${escaped}"
30
+ delay 0.2
31
+ -- Submit with Enter
32
+ key code 36
33
+ end tell
34
+ end tell
35
+ `;
36
+ (0, child_process_1.execSync)(`osascript -e '${script.replace(/'/g, "'\\''")}'`, {
37
+ timeout: 10000,
38
+ });
39
+ console.log(chalk_1.default.hex('#22C55E')(' ✓ ') +
40
+ chalk_1.default.white('Sent to Cursor IDE'));
41
+ }
42
+ catch (err) {
43
+ console.log(chalk_1.default.hex('#EF4444')(' ✗ ') +
44
+ chalk_1.default.gray('Failed to send to Cursor. Is it running?'));
45
+ }
46
+ }
14
47
  function generatePairCode() {
15
48
  return Math.floor(100000 + Math.random() * 900000).toString();
16
49
  }
17
50
  const PAIR_CODE = generatePairCode();
18
- const clients = new Map();
19
- function getLocalIP() {
20
- const interfaces = os_1.default.networkInterfaces();
21
- for (const name of Object.keys(interfaces)) {
22
- for (const iface of interfaces[name] || []) {
23
- if (iface.family === 'IPv4' && !iface.internal) {
24
- return iface.address;
25
- }
26
- }
27
- }
28
- return 'localhost';
29
- }
30
- function findPeer(clientId) {
31
- const client = clients.get(clientId);
32
- if (!client)
33
- return undefined;
34
- for (const [, other] of clients) {
35
- if (other.id !== clientId &&
36
- other.token === client.token &&
37
- other.type !== client.type) {
38
- return other;
39
- }
40
- }
41
- return undefined;
42
- }
51
+ let ws = null;
52
+ let reconnectTimer = null;
43
53
  function banner() {
44
- const ip = getLocalIP();
45
54
  console.clear();
46
55
  console.log('');
47
56
  console.log(chalk_1.default.hex('#A855F7').bold(' ╔══════════════════════════════════════╗'));
@@ -56,145 +65,97 @@ function banner() {
56
65
  chalk_1.default.bgHex('#A855F7').white.bold(` ${PAIR_CODE.split('').join(' ')} `));
57
66
  console.log('');
58
67
  console.log(chalk_1.default.gray(' ─────────────────────────────────────────'));
59
- console.log(chalk_1.default.gray(' Host: ') + chalk_1.default.white(ip));
60
- console.log(chalk_1.default.gray(' Port: ') + chalk_1.default.white(String(PORT)));
68
+ console.log(chalk_1.default.gray(' Bridge: ') + chalk_1.default.white(BRIDGE_URL));
61
69
  console.log(chalk_1.default.gray(' ─────────────────────────────────────────'));
62
70
  console.log('');
63
- console.log(chalk_1.default.gray(' Waiting for mobile connection...'));
71
+ console.log(chalk_1.default.gray(' Connecting to bridge server...'));
64
72
  console.log('');
65
73
  }
66
- const wss = new ws_1.WebSocketServer({ port: PORT });
67
- wss.on('error', error => {
68
- console.error(chalk_1.default.red(' WebSocket error:'), error.message);
69
- });
70
- wss.on('connection', (ws) => {
71
- const clientId = (0, uuid_1.v4)();
72
- ws.on('error', error => {
73
- console.error(chalk_1.default.red(` Client error:`), error.message);
74
- clients.delete(clientId);
74
+ function connect() {
75
+ ws = new ws_1.default(BRIDGE_URL);
76
+ ws.on('open', () => {
77
+ console.log(chalk_1.default.hex('#22C55E')(' ✓ ') +
78
+ chalk_1.default.white('Connected to bridge server'));
79
+ ws.send(JSON.stringify({
80
+ type: 'pair',
81
+ payload: { pairCode: PAIR_CODE, clientType: 'desktop' },
82
+ timestamp: Date.now(),
83
+ }));
84
+ console.log(chalk_1.default.gray(' Waiting for mobile device...'));
85
+ console.log('');
75
86
  });
76
87
  ws.on('message', (raw) => {
77
88
  try {
78
89
  const message = JSON.parse(raw.toString());
79
90
  switch (message.type) {
80
- case 'pair': {
81
- const { pairCode, clientType } = message.payload;
82
- // Pair code doğrula
83
- if (pairCode !== PAIR_CODE) {
84
- ws.send(JSON.stringify({
85
- type: 'error',
86
- payload: { message: 'Invalid pair code' },
87
- timestamp: Date.now(),
88
- }));
89
- console.log(chalk_1.default.hex('#EF4444')(' ✗ ') +
90
- chalk_1.default.gray(`Invalid pair code attempt: ${pairCode}`));
91
- return;
92
- }
93
- clients.set(clientId, {
94
- id: clientId,
95
- ws,
96
- type: clientType,
97
- token: TOKEN,
98
- });
99
- const peer = findPeer(clientId);
100
- ws.send(JSON.stringify({
101
- type: 'status',
102
- payload: {
103
- status: peer ? 'connected' : 'waiting',
104
- clientId,
105
- host: getLocalIP(),
106
- port: PORT,
107
- },
108
- timestamp: Date.now(),
109
- }));
110
- if (peer) {
111
- peer.ws.send(JSON.stringify({
112
- type: 'status',
113
- payload: { status: 'connected' },
114
- timestamp: Date.now(),
115
- }));
91
+ case 'status': {
92
+ const status = message.payload.status;
93
+ if (status === 'connected') {
116
94
  console.log(chalk_1.default.hex('#22C55E')(' ✓ ') +
117
- chalk_1.default.white(`${clientType} paired successfully!`));
95
+ chalk_1.default.white('Mobile device paired successfully!'));
118
96
  }
119
- else {
120
- console.log(chalk_1.default.hex('#22C55E')(' ') +
121
- chalk_1.default.white(`${clientType} connected with pair code`));
97
+ else if (status === 'waiting') {
98
+ console.log(chalk_1.default.gray(' Waiting for mobile device...'));
122
99
  }
123
- break;
124
- }
125
- case 'command': {
126
- const peer = findPeer(clientId);
127
- if (peer && peer.ws.readyState === ws_1.WebSocket.OPEN) {
128
- peer.ws.send(JSON.stringify({
129
- ...message,
130
- from: clientId,
131
- timestamp: Date.now(),
132
- }));
133
- console.log(chalk_1.default.hex('#A855F7')(' → ') +
134
- chalk_1.default.gray('Command forwarded to desktop'));
135
- }
136
- break;
137
- }
138
- case 'response': {
139
- const peer = findPeer(clientId);
140
- if (peer && peer.ws.readyState === ws_1.WebSocket.OPEN) {
141
- peer.ws.send(JSON.stringify({
142
- ...message,
143
- from: clientId,
144
- timestamp: Date.now(),
145
- }));
146
- console.log(chalk_1.default.hex('#A855F7')(' ← ') +
147
- chalk_1.default.gray('Response forwarded to mobile'));
100
+ else if (status === 'disconnected') {
101
+ console.log(chalk_1.default.hex('#EF4444')(' ✗ ') +
102
+ chalk_1.default.gray('Mobile device disconnected'));
148
103
  }
149
104
  break;
150
105
  }
151
- case 'ping': {
106
+ case 'command': {
107
+ const prompt = message.payload.prompt;
108
+ console.log(chalk_1.default.hex('#A855F7')(' → ') +
109
+ chalk_1.default.white('Command received: ') +
110
+ chalk_1.default.gray(prompt.substring(0, 80) + (prompt.length > 80 ? '...' : '')));
111
+ sendToCursor(prompt);
152
112
  ws.send(JSON.stringify({
153
- type: 'pong',
154
- payload: {},
113
+ type: 'response',
114
+ payload: {
115
+ status: 'sent',
116
+ message: 'Sent to Cursor IDE',
117
+ },
155
118
  timestamp: Date.now(),
156
119
  }));
157
120
  break;
158
121
  }
122
+ case 'error': {
123
+ console.log(chalk_1.default.hex('#EF4444')(' ✗ ') +
124
+ chalk_1.default.gray(message.payload.message || 'Unknown error'));
125
+ break;
126
+ }
159
127
  }
160
128
  }
161
129
  catch {
162
- ws.send(JSON.stringify({
163
- type: 'error',
164
- payload: { message: 'Invalid message format' },
165
- }));
130
+ console.warn(chalk_1.default.gray(' Invalid message received'));
166
131
  }
167
132
  });
168
133
  ws.on('close', () => {
169
- const client = clients.get(clientId);
170
- if (client) {
171
- const peer = findPeer(clientId);
172
- if (peer && peer.ws.readyState === ws_1.WebSocket.OPEN) {
173
- peer.ws.send(JSON.stringify({
174
- type: 'status',
175
- payload: { status: 'disconnected' },
176
- timestamp: Date.now(),
177
- }));
178
- }
179
- console.log(chalk_1.default.hex('#EF4444')(' ✗ ') +
180
- chalk_1.default.gray(`${client.type} device disconnected`));
181
- clients.delete(clientId);
182
- }
134
+ console.log(chalk_1.default.hex('#EF4444')(' ✗ ') +
135
+ chalk_1.default.gray('Disconnected from bridge server'));
136
+ scheduleReconnect();
183
137
  });
184
- });
185
- // Heartbeat
186
- const heartbeat = setInterval(() => {
187
- clients.forEach(client => {
188
- if (client.ws.readyState === ws_1.WebSocket.OPEN) {
189
- client.ws.ping();
190
- }
138
+ ws.on('error', (err) => {
139
+ console.error(chalk_1.default.hex('#EF4444')(' ✗ ') +
140
+ chalk_1.default.gray(`Connection error: ${err.message}`));
191
141
  });
192
- }, 30000);
142
+ }
143
+ function scheduleReconnect() {
144
+ if (reconnectTimer)
145
+ return;
146
+ console.log(chalk_1.default.gray(' Reconnecting in 3s...'));
147
+ reconnectTimer = setTimeout(() => {
148
+ reconnectTimer = null;
149
+ connect();
150
+ }, 3000);
151
+ }
193
152
  banner();
153
+ connect();
194
154
  process.on('SIGINT', () => {
195
155
  console.log('');
196
156
  console.log(chalk_1.default.gray(' Bridge stopped.'));
197
- clearInterval(heartbeat);
198
- wss.close();
157
+ if (reconnectTimer)
158
+ clearTimeout(reconnectTimer);
159
+ ws?.close();
199
160
  process.exit(0);
200
161
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursor-bridge",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "CLI bridge to connect IDE For Cursor mobile app with desktop Cursor IDE",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -16,9 +16,7 @@
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
18
  "chalk": "^4.1.2",
19
- "ws": "^8.20.0",
20
- "uuid": "^13.0.0",
21
- "qrcode-terminal": "^0.12.0"
19
+ "ws": "^8.20.0"
22
20
  },
23
21
  "devDependencies": {
24
22
  "@types/ws": "^8.18.1",
package/src/index.ts CHANGED
@@ -1,67 +1,64 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { WebSocketServer, WebSocket } from 'ws';
4
- import { v4 as uuidv4 } from 'uuid';
3
+ import WebSocket from 'ws';
4
+ import { execSync } from 'child_process';
5
5
  import chalk from 'chalk';
6
- import os from 'os';
7
6
 
8
- const PORT = Number(process.argv[2]) || 9090;
9
- const TOKEN = uuidv4();
7
+ const BRIDGE_URL = 'wss://cursor-226b2ae97542.herokuapp.com';
8
+
9
+ function sendToCursor(prompt: string): void {
10
+ try {
11
+ // Escape special characters for AppleScript
12
+ const escaped = prompt
13
+ .replace(/\\/g, '\\\\')
14
+ .replace(/"/g, '\\"')
15
+ .replace(/\n/g, '\\n');
16
+
17
+ const script = `
18
+ tell application "Cursor"
19
+ activate
20
+ end tell
21
+ delay 0.5
22
+ tell application "System Events"
23
+ tell process "Cursor"
24
+ -- Open Composer with Cmd+I
25
+ keystroke "i" using command down
26
+ delay 0.3
27
+ -- Type the prompt
28
+ keystroke "${escaped}"
29
+ delay 0.2
30
+ -- Submit with Enter
31
+ key code 36
32
+ end tell
33
+ end tell
34
+ `;
35
+
36
+ execSync(`osascript -e '${script.replace(/'/g, "'\\''")}'`, {
37
+ timeout: 10000,
38
+ });
39
+
40
+ console.log(
41
+ chalk.hex('#22C55E')(' ✓ ') +
42
+ chalk.white('Sent to Cursor IDE'),
43
+ );
44
+ } catch (err) {
45
+ console.log(
46
+ chalk.hex('#EF4444')(' ✗ ') +
47
+ chalk.gray('Failed to send to Cursor. Is it running?'),
48
+ );
49
+ }
50
+ }
10
51
 
11
- // 6 haneli pair code üret
12
52
  function generatePairCode(): string {
13
53
  return Math.floor(100000 + Math.random() * 900000).toString();
14
54
  }
15
55
 
16
56
  const PAIR_CODE = generatePairCode();
17
57
 
18
- interface BridgeMessage {
19
- type: string;
20
- payload: Record<string, unknown>;
21
- from?: string;
22
- timestamp: number;
23
- }
24
-
25
- interface ConnectedClient {
26
- id: string;
27
- ws: WebSocket;
28
- type: 'mobile' | 'desktop';
29
- token: string;
30
- }
31
-
32
- const clients = new Map<string, ConnectedClient>();
33
-
34
- function getLocalIP(): string {
35
- const interfaces = os.networkInterfaces();
36
- for (const name of Object.keys(interfaces)) {
37
- for (const iface of interfaces[name] || []) {
38
- if (iface.family === 'IPv4' && !iface.internal) {
39
- return iface.address;
40
- }
41
- }
42
- }
43
- return 'localhost';
44
- }
45
-
46
- function findPeer(clientId: string): ConnectedClient | undefined {
47
- const client = clients.get(clientId);
48
- if (!client) return undefined;
49
-
50
- for (const [, other] of clients) {
51
- if (
52
- other.id !== clientId &&
53
- other.token === client.token &&
54
- other.type !== client.type
55
- ) {
56
- return other;
57
- }
58
- }
59
- return undefined;
60
- }
58
+ let ws: WebSocket | null = null;
59
+ let reconnectTimer: ReturnType<typeof setTimeout> | null = null;
61
60
 
62
61
  function banner() {
63
- const ip = getLocalIP();
64
-
65
62
  console.clear();
66
63
  console.log('');
67
64
  console.log(
@@ -89,197 +86,128 @@ function banner() {
89
86
  chalk.gray(' ─────────────────────────────────────────'),
90
87
  );
91
88
  console.log(
92
- chalk.gray(' Host: ') + chalk.white(ip),
93
- );
94
- console.log(
95
- chalk.gray(' Port: ') + chalk.white(String(PORT)),
89
+ chalk.gray(' Bridge: ') + chalk.white(BRIDGE_URL),
96
90
  );
97
91
  console.log(
98
92
  chalk.gray(' ─────────────────────────────────────────'),
99
93
  );
100
94
  console.log('');
101
- console.log(chalk.gray(' Waiting for mobile connection...'));
95
+ console.log(chalk.gray(' Connecting to bridge server...'));
102
96
  console.log('');
103
97
  }
104
98
 
105
- const wss = new WebSocketServer({ port: PORT });
106
-
107
- wss.on('error', error => {
108
- console.error(chalk.red(' WebSocket error:'), error.message);
109
- });
110
-
111
- wss.on('connection', (ws: WebSocket) => {
112
- const clientId = uuidv4();
113
-
114
- ws.on('error', error => {
115
- console.error(chalk.red(` Client error:`), error.message);
116
- clients.delete(clientId);
99
+ function connect() {
100
+ ws = new WebSocket(BRIDGE_URL);
101
+
102
+ ws.on('open', () => {
103
+ console.log(
104
+ chalk.hex('#22C55E')(' ✓ ') +
105
+ chalk.white('Connected to bridge server'),
106
+ );
107
+
108
+ ws!.send(
109
+ JSON.stringify({
110
+ type: 'pair',
111
+ payload: { pairCode: PAIR_CODE, clientType: 'desktop' },
112
+ timestamp: Date.now(),
113
+ }),
114
+ );
115
+
116
+ console.log(chalk.gray(' Waiting for mobile device...'));
117
+ console.log('');
117
118
  });
118
119
 
119
120
  ws.on('message', (raw: Buffer) => {
120
121
  try {
121
- const message: BridgeMessage = JSON.parse(raw.toString());
122
+ const message = JSON.parse(raw.toString());
122
123
 
123
124
  switch (message.type) {
124
- case 'pair': {
125
- const { pairCode, clientType } = message.payload as {
126
- pairCode: string;
127
- clientType: 'mobile' | 'desktop';
128
- };
129
-
130
- // Pair code doğrula
131
- if (pairCode !== PAIR_CODE) {
132
- ws.send(
133
- JSON.stringify({
134
- type: 'error',
135
- payload: { message: 'Invalid pair code' },
136
- timestamp: Date.now(),
137
- }),
125
+ case 'status': {
126
+ const status = message.payload.status as string;
127
+ if (status === 'connected') {
128
+ console.log(
129
+ chalk.hex('#22C55E')(' ✓ ') +
130
+ chalk.white('Mobile device paired successfully!'),
138
131
  );
132
+ } else if (status === 'waiting') {
133
+ console.log(chalk.gray(' Waiting for mobile device...'));
134
+ } else if (status === 'disconnected') {
139
135
  console.log(
140
136
  chalk.hex('#EF4444')(' ✗ ') +
141
- chalk.gray(`Invalid pair code attempt: ${pairCode}`),
137
+ chalk.gray('Mobile device disconnected'),
142
138
  );
143
- return;
144
139
  }
140
+ break;
141
+ }
145
142
 
146
- clients.set(clientId, {
147
- id: clientId,
148
- ws,
149
- type: clientType,
150
- token: TOKEN,
151
- });
143
+ case 'command': {
144
+ const prompt = message.payload.prompt as string;
145
+ console.log(
146
+ chalk.hex('#A855F7')(' → ') +
147
+ chalk.white('Command received: ') +
148
+ chalk.gray(prompt.substring(0, 80) + (prompt.length > 80 ? '...' : '')),
149
+ );
152
150
 
153
- const peer = findPeer(clientId);
151
+ sendToCursor(prompt);
154
152
 
155
- ws.send(
153
+ ws!.send(
156
154
  JSON.stringify({
157
- type: 'status',
155
+ type: 'response',
158
156
  payload: {
159
- status: peer ? 'connected' : 'waiting',
160
- clientId,
161
- host: getLocalIP(),
162
- port: PORT,
157
+ status: 'sent',
158
+ message: 'Sent to Cursor IDE',
163
159
  },
164
160
  timestamp: Date.now(),
165
161
  }),
166
162
  );
167
-
168
- if (peer) {
169
- peer.ws.send(
170
- JSON.stringify({
171
- type: 'status',
172
- payload: { status: 'connected' },
173
- timestamp: Date.now(),
174
- }),
175
- );
176
- console.log(
177
- chalk.hex('#22C55E')(' ✓ ') +
178
- chalk.white(`${clientType} paired successfully!`),
179
- );
180
- } else {
181
- console.log(
182
- chalk.hex('#22C55E')(' ✓ ') +
183
- chalk.white(`${clientType} connected with pair code`),
184
- );
185
- }
186
- break;
187
- }
188
-
189
- case 'command': {
190
- const peer = findPeer(clientId);
191
- if (peer && peer.ws.readyState === WebSocket.OPEN) {
192
- peer.ws.send(
193
- JSON.stringify({
194
- ...message,
195
- from: clientId,
196
- timestamp: Date.now(),
197
- }),
198
- );
199
- console.log(
200
- chalk.hex('#A855F7')(' → ') +
201
- chalk.gray('Command forwarded to desktop'),
202
- );
203
- }
204
- break;
205
- }
206
-
207
- case 'response': {
208
- const peer = findPeer(clientId);
209
- if (peer && peer.ws.readyState === WebSocket.OPEN) {
210
- peer.ws.send(
211
- JSON.stringify({
212
- ...message,
213
- from: clientId,
214
- timestamp: Date.now(),
215
- }),
216
- );
217
- console.log(
218
- chalk.hex('#A855F7')(' ← ') +
219
- chalk.gray('Response forwarded to mobile'),
220
- );
221
- }
222
163
  break;
223
164
  }
224
165
 
225
- case 'ping': {
226
- ws.send(
227
- JSON.stringify({
228
- type: 'pong',
229
- payload: {},
230
- timestamp: Date.now(),
231
- }),
166
+ case 'error': {
167
+ console.log(
168
+ chalk.hex('#EF4444')(' ✗ ') +
169
+ chalk.gray(message.payload.message || 'Unknown error'),
232
170
  );
233
171
  break;
234
172
  }
235
173
  }
236
174
  } catch {
237
- ws.send(
238
- JSON.stringify({
239
- type: 'error',
240
- payload: { message: 'Invalid message format' },
241
- }),
242
- );
175
+ console.warn(chalk.gray(' Invalid message received'));
243
176
  }
244
177
  });
245
178
 
246
179
  ws.on('close', () => {
247
- const client = clients.get(clientId);
248
- if (client) {
249
- const peer = findPeer(clientId);
250
- if (peer && peer.ws.readyState === WebSocket.OPEN) {
251
- peer.ws.send(
252
- JSON.stringify({
253
- type: 'status',
254
- payload: { status: 'disconnected' },
255
- timestamp: Date.now(),
256
- }),
257
- );
258
- }
259
- console.log(
260
- chalk.hex('#EF4444')(' ✗ ') +
261
- chalk.gray(`${client.type} device disconnected`),
262
- );
263
- clients.delete(clientId);
264
- }
180
+ console.log(
181
+ chalk.hex('#EF4444')(' ✗ ') +
182
+ chalk.gray('Disconnected from bridge server'),
183
+ );
184
+ scheduleReconnect();
265
185
  });
266
- });
267
186
 
268
- // Heartbeat
269
- const heartbeat = setInterval(() => {
270
- clients.forEach(client => {
271
- if (client.ws.readyState === WebSocket.OPEN) {
272
- client.ws.ping();
273
- }
187
+ ws.on('error', (err) => {
188
+ console.error(
189
+ chalk.hex('#EF4444')(' ✗ ') +
190
+ chalk.gray(`Connection error: ${err.message}`),
191
+ );
274
192
  });
275
- }, 30000);
193
+ }
194
+
195
+ function scheduleReconnect() {
196
+ if (reconnectTimer) return;
197
+ console.log(chalk.gray(' Reconnecting in 3s...'));
198
+ reconnectTimer = setTimeout(() => {
199
+ reconnectTimer = null;
200
+ connect();
201
+ }, 3000);
202
+ }
276
203
 
277
204
  banner();
205
+ connect();
278
206
 
279
207
  process.on('SIGINT', () => {
280
208
  console.log('');
281
209
  console.log(chalk.gray(' Bridge stopped.'));
282
- clearInterval(heartbeat);
283
- wss.close();
210
+ if (reconnectTimer) clearTimeout(reconnectTimer);
211
+ ws?.close();
284
212
  process.exit(0);
285
213
  });