shell-mirror 1.5.126 → 1.5.128

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shell-mirror",
3
- "version": "1.5.126",
3
+ "version": "1.5.128",
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": {
@@ -231,6 +231,17 @@
231
231
  50% { opacity: 0.5; }
232
232
  }
233
233
 
234
+ @keyframes calm-pulsate {
235
+ 0%, 100% {
236
+ box-shadow: 0 0 0 rgba(255, 170, 68, 0);
237
+ border-color: #444;
238
+ }
239
+ 50% {
240
+ box-shadow: 0 0 12px rgba(255, 170, 68, 0.6);
241
+ border-color: #ffaa44;
242
+ }
243
+ }
244
+
234
245
  /* Header Buttons */
235
246
  .header-btn {
236
247
  background: transparent;
@@ -252,6 +263,10 @@
252
263
  border-color: #667eea;
253
264
  }
254
265
 
266
+ .dashboard-btn.pulsate {
267
+ animation: calm-pulsate 2s ease-in-out infinite;
268
+ }
269
+
255
270
  .help-btn .btn-text {
256
271
  display: none;
257
272
  }
@@ -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,36 @@ 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
+
326
+ // Make Dashboard button pulsate calmly to guide user back
327
+ const dashboardBtn = document.querySelector('.dashboard-btn');
328
+ if (dashboardBtn) {
329
+ dashboardBtn.classList.add('pulsate');
330
+ }
325
331
  }
326
332
  }, 60000);
327
333
 
@@ -341,19 +347,19 @@ async function initialize() {
341
347
 
342
348
  if (directConnectionSuccess) {
343
349
  console.log('[CLIENT] ✅ Direct connection established - no server needed!');
344
- setConnectionMessage('Connected via local network!', true);
350
+ setConnectionMessage('Connected via local network!', true);
345
351
  return;
346
352
  }
347
353
 
348
354
  console.log('[CLIENT] ⚠️ Direct connection failed, falling back to WebRTC signaling...');
349
- setConnectionMessage('🌐 Attempting WebRTC connection...', true);
355
+ setConnectionMessage('Attempting WebRTC connection...', true);
350
356
  await initializeWebRTCSignaling();
351
357
  }
352
358
 
353
359
  async function tryDirectConnection() {
354
360
  console.log('[CLIENT] 🔗 Attempting direct connection to agent...');
355
361
  updateConnectionStatus('connecting');
356
- setConnectionMessage('🔍 Trying direct connection to local network...', true);
362
+ setConnectionMessage('Trying direct connection to local network...', true);
357
363
 
358
364
  // Get agent data from API to find local connection details
359
365
  try {
@@ -465,7 +471,7 @@ function setupDirectConnection(directWs) {
465
471
 
466
472
  // Clear connection timeout warnings
467
473
  clearConnectionTimeouts();
468
- setConnectionMessage('Session created successfully!', false);
474
+ setConnectionMessage('Session created successfully!', false);
469
475
 
470
476
  // Update current session
471
477
  currentSession = {
@@ -645,7 +651,7 @@ async function initializeWebRTCSignaling() {
645
651
  if (nextData.sessionId) {
646
652
  // Clear connection timeout warnings
647
653
  clearConnectionTimeouts();
648
- setConnectionMessage('Session connected!', false);
654
+ setConnectionMessage('Session connected!', false);
649
655
 
650
656
  currentSession = {
651
657
  id: nextData.sessionId,
@@ -870,9 +876,9 @@ async function createPeerConnection() {
870
876
  console.log('[CLIENT] ❌ ICE connection failed - no viable candidates');
871
877
  console.log('[CLIENT] 💡 Troubleshooting: This may be due to firewall/NAT issues or blocked STUN servers');
872
878
  updateConnectionStatus('disconnected');
873
- setConnectionMessage('Unable to connect - Agent may be offline', false);
874
- term.write('\r\n\r\n❌ Connection failed: Network connectivity issues\r\n');
875
- 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');
876
882
  term.write(' • Firewall blocking WebRTC traffic\r\n');
877
883
  term.write(' • Corporate network restrictions\r\n');
878
884
  term.write(' • STUN/TURN servers unreachable\r\n');
@@ -973,15 +979,15 @@ function setupDataChannel() {
973
979
  dataChannel.onclose = () => {
974
980
  console.log('[CLIENT] Data channel closed.');
975
981
  updateConnectionStatus('disconnected');
976
- term.write('\r\n\r\n\x1b[31m❌ Terminal session ended.\x1b[0m\r\n');
977
- 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');
978
984
  };
979
985
 
980
986
  dataChannel.onerror = (error) => {
981
987
  console.error('[CLIENT] Data channel error:', error);
982
988
  updateConnectionStatus('disconnected');
983
- term.write('\r\n\r\n\x1b[31m❌ Data channel error occurred.\x1b[0m\r\n');
984
- 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');
985
991
  };
986
992
 
987
993
  term.onData((data) => {
@@ -1285,7 +1291,7 @@ function createNewSession() {
1285
1291
  console.error('[CLIENT] ❌ Cannot create session - no active connection');
1286
1292
  console.error('[CLIENT] ws:', ws ? ws.readyState : 'null',
1287
1293
  'dataChannel:', dataChannel ? dataChannel.readyState : 'null');
1288
- 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');
1289
1295
  }
1290
1296
  }
1291
1297
 
@@ -1349,7 +1355,7 @@ function handleSessionMessage(message) {
1349
1355
  case 'session-ended':
1350
1356
  // Only show if this is for the current session (ignore closed session messages)
1351
1357
  if (!message.sessionId || (currentSession && message.sessionId === currentSession.id)) {
1352
- 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`);
1353
1359
  if (message.code) {
1354
1360
  term.write(`Exit code: ${message.code}\r\n`);
1355
1361
  }
@@ -1358,8 +1364,8 @@ function handleSessionMessage(message) {
1358
1364
  case 'session-terminated':
1359
1365
  // Only show if this is for the current session (ignore closed session messages)
1360
1366
  if (!message.sessionId || (currentSession && message.sessionId === currentSession.id)) {
1361
- term.write(`\r\n\x1b[31m❌ Session terminated\x1b[0m\r\n`);
1362
- 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');
1363
1369
  }
1364
1370
  break;
1365
1371
  case 'session-closed':
@@ -1371,7 +1377,7 @@ function handleSessionMessage(message) {
1371
1377
  }
1372
1378
  break;
1373
1379
  case 'error':
1374
- 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`);
1375
1381
  break;
1376
1382
  }
1377
1383
  }