shell-mirror 1.5.127 → 1.5.129

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.
@@ -7,6 +7,7 @@ const os = require('os');
7
7
  const { v4: uuidv4 } = require('uuid');
8
8
  const fs = require('fs');
9
9
  const https = require('https');
10
+ const { exec } = require('child_process');
10
11
 
11
12
  // Enhanced logging to file
12
13
  const LOG_FILE = path.join(__dirname, 'agent-debug.log');
@@ -532,9 +533,22 @@ function connectToSignalingServer() {
532
533
 
533
534
  ws.on('open', () => {
534
535
  logToFile('✅ Connected to signaling server.');
535
-
536
+
536
537
  // Start heartbeat system to maintain agent status
537
538
  startHeartbeatSystem();
539
+
540
+ // Open dashboard in default browser
541
+ const dashboardUrl = 'https://shellmirror.app/app/dashboard.html';
542
+ logToFile(`🌐 Opening dashboard in browser: ${dashboardUrl}`);
543
+
544
+ exec(`open "${dashboardUrl}"`, (error) => {
545
+ if (error) {
546
+ logToFile(`⚠️ Could not open browser automatically: ${error.message}`);
547
+ logToFile(`💡 Please open ${dashboardUrl} manually in your browser`);
548
+ } else {
549
+ logToFile('✅ Dashboard opened in browser');
550
+ }
551
+ });
538
552
  });
539
553
 
540
554
  ws.on('message', async (message) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shell-mirror",
3
- "version": "1.5.127",
3
+ "version": "1.5.129",
4
4
  "description": "Access your Mac shell from any device securely. Perfect for mobile coding with Claude Code CLI, Gemini CLI, and any shell tool.",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -233,12 +233,12 @@
233
233
 
234
234
  @keyframes calm-pulsate {
235
235
  0%, 100% {
236
- box-shadow: 0 0 0 rgba(102, 126, 234, 0);
236
+ box-shadow: 0 0 0 rgba(255, 170, 68, 0);
237
237
  border-color: #444;
238
238
  }
239
239
  50% {
240
- box-shadow: 0 0 12px rgba(102, 126, 234, 0.6);
241
- border-color: #667eea;
240
+ box-shadow: 0 0 12px rgba(255, 170, 68, 0.6);
241
+ border-color: #ffaa44;
242
242
  }
243
243
  }
244
244
 
@@ -274,7 +274,7 @@ function startConnection() {
274
274
  term.open(document.getElementById('terminal'));
275
275
 
276
276
  // Show initial connection message
277
- setConnectionMessage('🔗 Connecting to agent...', true);
277
+ setConnectionMessage('Connecting to agent...', true);
278
278
 
279
279
  // Initialize session display (shows header with connection status even before session exists)
280
280
  updateSessionDisplay();
@@ -298,30 +298,30 @@ function startConnection() {
298
298
  // Set up connection timeout warnings
299
299
  const timeout10s = setTimeout(() => {
300
300
  if (!currentSession) {
301
- setConnectionMessage('⏱️ Taking longer than usual... Please wait', true);
302
- term.write('\r\n\x1b[33m⏱️ Connection is taking longer than expected...\x1b[0m\r\n');
301
+ setConnectionMessage('Taking longer than usual... Please wait', true);
302
+ term.write('\r\n\x1b[33mConnection is taking longer than expected...\x1b[0m\r\n');
303
303
  }
304
304
  }, 10000);
305
305
 
306
306
  const timeout30s = setTimeout(() => {
307
307
  if (!currentSession) {
308
- setConnectionMessage('⚠️ Connection very slow - Agent may be offline', true);
309
- term.write('\x1b[33m⚠️ Still trying to connect. The agent may be offline or unreachable.\x1b[0m\r\n');
310
- term.write('\x1b[36m💡 Tip: Check the agent status on the Dashboard\x1b[0m\r\n');
308
+ setConnectionMessage('Connection very slow - Agent may be offline', true);
309
+ term.write('\x1b[33mStill trying to connect. The agent may be offline or unreachable.\x1b[0m\r\n');
310
+ term.write('\x1b[36mTip: Check the agent status on the Dashboard\x1b[0m\r\n');
311
311
  }
312
312
  }, 30000);
313
313
 
314
314
  const timeout60s = setTimeout(() => {
315
315
  if (!currentSession) {
316
316
  updateConnectionStatus('disconnected');
317
- setConnectionMessage('Failed to connect - Agent or session unavailable', false);
318
- term.write('\r\n\r\n\x1b[31m❌ Connection Failed\x1b[0m\r\n');
317
+ setConnectionMessage('Failed to connect - Agent or session unavailable', false);
318
+ term.write('\r\n\r\n\x1b[31mConnection Failed\x1b[0m\r\n');
319
319
  term.write('\x1b[33mThe agent or session you requested is not available.\x1b[0m\r\n');
320
320
  term.write('\r\n\x1b[36mPossible reasons:\x1b[0m\r\n');
321
321
  term.write(' • Agent is offline or shut down\r\n');
322
322
  term.write(' • Session was terminated\r\n');
323
323
  term.write(' • Network connectivity issues\r\n');
324
- term.write('\r\n\x1b[36m💡 Click Dashboard to return and try another session\x1b[0m\r\n');
324
+ term.write('\r\n\x1b[36mClick Dashboard to return and try another session\x1b[0m\r\n');
325
325
 
326
326
  // Make Dashboard button pulsate calmly to guide user back
327
327
  const dashboardBtn = document.querySelector('.dashboard-btn');
@@ -347,19 +347,19 @@ async function initialize() {
347
347
 
348
348
  if (directConnectionSuccess) {
349
349
  console.log('[CLIENT] ✅ Direct connection established - no server needed!');
350
- setConnectionMessage('Connected via local network!', true);
350
+ setConnectionMessage('Connected via local network!', true);
351
351
  return;
352
352
  }
353
353
 
354
354
  console.log('[CLIENT] ⚠️ Direct connection failed, falling back to WebRTC signaling...');
355
- setConnectionMessage('🌐 Attempting WebRTC connection...', true);
355
+ setConnectionMessage('Attempting WebRTC connection...', true);
356
356
  await initializeWebRTCSignaling();
357
357
  }
358
358
 
359
359
  async function tryDirectConnection() {
360
360
  console.log('[CLIENT] 🔗 Attempting direct connection to agent...');
361
361
  updateConnectionStatus('connecting');
362
- setConnectionMessage('🔍 Trying direct connection to local network...', true);
362
+ setConnectionMessage('Trying direct connection to local network...', true);
363
363
 
364
364
  // Get agent data from API to find local connection details
365
365
  try {
@@ -471,7 +471,7 @@ function setupDirectConnection(directWs) {
471
471
 
472
472
  // Clear connection timeout warnings
473
473
  clearConnectionTimeouts();
474
- setConnectionMessage('Session created successfully!', false);
474
+ setConnectionMessage('Session created successfully!', false);
475
475
 
476
476
  // Update current session
477
477
  currentSession = {
@@ -651,7 +651,7 @@ async function initializeWebRTCSignaling() {
651
651
  if (nextData.sessionId) {
652
652
  // Clear connection timeout warnings
653
653
  clearConnectionTimeouts();
654
- setConnectionMessage('Session connected!', false);
654
+ setConnectionMessage('Session connected!', false);
655
655
 
656
656
  currentSession = {
657
657
  id: nextData.sessionId,
@@ -876,9 +876,9 @@ async function createPeerConnection() {
876
876
  console.log('[CLIENT] ❌ ICE connection failed - no viable candidates');
877
877
  console.log('[CLIENT] 💡 Troubleshooting: This may be due to firewall/NAT issues or blocked STUN servers');
878
878
  updateConnectionStatus('disconnected');
879
- setConnectionMessage('Unable to connect - Agent may be offline', false);
880
- term.write('\r\n\r\n❌ Connection failed: Network connectivity issues\r\n');
881
- term.write('💡 This may be due to:\r\n');
879
+ setConnectionMessage('Unable to connect - Agent may be offline', false);
880
+ term.write('\r\n\r\nConnection failed: Network connectivity issues\r\n');
881
+ term.write('This may be due to:\r\n');
882
882
  term.write(' • Firewall blocking WebRTC traffic\r\n');
883
883
  term.write(' • Corporate network restrictions\r\n');
884
884
  term.write(' • STUN/TURN servers unreachable\r\n');
@@ -979,15 +979,15 @@ function setupDataChannel() {
979
979
  dataChannel.onclose = () => {
980
980
  console.log('[CLIENT] Data channel closed.');
981
981
  updateConnectionStatus('disconnected');
982
- term.write('\r\n\r\n\x1b[31m❌ Terminal session ended.\x1b[0m\r\n');
983
- term.write('🔄 Click Dashboard to return and start a new session\r\n');
982
+ term.write('\r\n\r\n\x1b[31mTerminal session ended.\x1b[0m\r\n');
983
+ term.write('Click Dashboard to return and start a new session\r\n');
984
984
  };
985
985
 
986
986
  dataChannel.onerror = (error) => {
987
987
  console.error('[CLIENT] Data channel error:', error);
988
988
  updateConnectionStatus('disconnected');
989
- term.write('\r\n\r\n\x1b[31m❌ Data channel error occurred.\x1b[0m\r\n');
990
- term.write('🔄 Click Dashboard to return and try again\r\n');
989
+ term.write('\r\n\r\n\x1b[31mData channel error occurred.\x1b[0m\r\n');
990
+ term.write('Click Dashboard to return and try again\r\n');
991
991
  };
992
992
 
993
993
  term.onData((data) => {
@@ -1291,7 +1291,7 @@ function createNewSession() {
1291
1291
  console.error('[CLIENT] ❌ Cannot create session - no active connection');
1292
1292
  console.error('[CLIENT] ws:', ws ? ws.readyState : 'null',
1293
1293
  'dataChannel:', dataChannel ? dataChannel.readyState : 'null');
1294
- term.write('\r\n\x1b[31m❌ Cannot create session - not connected\x1b[0m\r\n');
1294
+ term.write('\r\n\x1b[31mCannot create session - not connected\x1b[0m\r\n');
1295
1295
  }
1296
1296
  }
1297
1297
 
@@ -1355,7 +1355,7 @@ function handleSessionMessage(message) {
1355
1355
  case 'session-ended':
1356
1356
  // Only show if this is for the current session (ignore closed session messages)
1357
1357
  if (!message.sessionId || (currentSession && message.sessionId === currentSession.id)) {
1358
- term.write(`\r\n\x1b[31m❌ Session ended: ${message.reason}\x1b[0m\r\n`);
1358
+ term.write(`\r\n\x1b[31mSession ended: ${message.reason}\x1b[0m\r\n`);
1359
1359
  if (message.code) {
1360
1360
  term.write(`Exit code: ${message.code}\r\n`);
1361
1361
  }
@@ -1364,8 +1364,8 @@ function handleSessionMessage(message) {
1364
1364
  case 'session-terminated':
1365
1365
  // Only show if this is for the current session (ignore closed session messages)
1366
1366
  if (!message.sessionId || (currentSession && message.sessionId === currentSession.id)) {
1367
- term.write(`\r\n\x1b[31m❌ Session terminated\x1b[0m\r\n`);
1368
- term.write('🔄 Click Dashboard to start a new session\r\n');
1367
+ term.write(`\r\n\x1b[31mSession terminated\x1b[0m\r\n`);
1368
+ term.write('Click Dashboard to start a new session\r\n');
1369
1369
  }
1370
1370
  break;
1371
1371
  case 'session-closed':
@@ -1377,7 +1377,7 @@ function handleSessionMessage(message) {
1377
1377
  }
1378
1378
  break;
1379
1379
  case 'error':
1380
- term.write(`\r\n\x1b[31m❌ Error: ${message.message}\x1b[0m\r\n`);
1380
+ term.write(`\r\n\x1b[31mError: ${message.message}\x1b[0m\r\n`);
1381
1381
  break;
1382
1382
  }
1383
1383
  }