shell-mirror 1.5.64 → 1.5.65

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 (2) hide show
  1. package/mac-agent/agent.js +84 -0
  2. package/package.json +1 -1
@@ -6,6 +6,7 @@ const pty = require('node-pty');
6
6
  const os = require('os');
7
7
  const { v4: uuidv4 } = require('uuid');
8
8
  const fs = require('fs');
9
+ const https = require('https');
9
10
 
10
11
  // Enhanced logging to file
11
12
  const LOG_FILE = path.join(__dirname, 'agent-debug.log');
@@ -410,12 +411,92 @@ const iceServers = [
410
411
  }
411
412
  ];
412
413
 
414
+ // --- Heartbeat System ---
415
+ let heartbeatInterval;
416
+
417
+ async function sendHeartbeat() {
418
+ try {
419
+ const heartbeatData = JSON.stringify({
420
+ agentId: AGENT_ID,
421
+ timestamp: Date.now(),
422
+ activeSessions: Object.keys(sessions).length
423
+ });
424
+
425
+ const options = {
426
+ hostname: 'shellmirror.app',
427
+ port: 443,
428
+ path: '/php-backend/api/agent-heartbeat.php',
429
+ method: 'POST',
430
+ headers: {
431
+ 'Content-Type': 'application/json',
432
+ 'Content-Length': Buffer.byteLength(heartbeatData),
433
+ 'X-Agent-Secret': 'mac-agent-secret-2024',
434
+ 'X-Agent-ID': AGENT_ID
435
+ }
436
+ };
437
+
438
+ const req = https.request(options, (res) => {
439
+ let responseData = '';
440
+ res.on('data', (chunk) => {
441
+ responseData += chunk;
442
+ });
443
+ res.on('end', () => {
444
+ if (res.statusCode === 200) {
445
+ try {
446
+ const result = JSON.parse(responseData);
447
+ if (result.success) {
448
+ logToFile(`💓 Heartbeat sent successfully`);
449
+ } else {
450
+ logToFile(`⚠️ Heartbeat failed: ${result.message}`);
451
+ }
452
+ } catch (error) {
453
+ logToFile(`⚠️ Heartbeat response parse error: ${error.message}`);
454
+ }
455
+ } else {
456
+ logToFile(`⚠️ Heartbeat HTTP error: ${res.statusCode}`);
457
+ }
458
+ });
459
+ });
460
+
461
+ req.on('error', (error) => {
462
+ logToFile(`❌ Heartbeat request failed: ${error.message}`);
463
+ });
464
+
465
+ req.write(heartbeatData);
466
+ req.end();
467
+
468
+ } catch (error) {
469
+ logToFile(`❌ Heartbeat error: ${error.message}`);
470
+ }
471
+ }
472
+
473
+ function startHeartbeatSystem() {
474
+ logToFile('💓 Starting heartbeat system (60 second interval)');
475
+
476
+ // Send initial heartbeat immediately
477
+ sendHeartbeat();
478
+
479
+ // Set up recurring heartbeat
480
+ heartbeatInterval = setInterval(sendHeartbeat, 60000); // 60 seconds
481
+ }
482
+
483
+ function stopHeartbeatSystem() {
484
+ if (heartbeatInterval) {
485
+ clearInterval(heartbeatInterval);
486
+ heartbeatInterval = null;
487
+ logToFile('💓 Heartbeat system stopped');
488
+ }
489
+ }
490
+
413
491
  function connectToSignalingServer() {
414
492
  logToFile(`🔌 Connecting to signaling server at ${SIGNALING_SERVER_URL}?role=agent&agentId=${AGENT_ID}`);
415
493
  ws = new WebSocket(`${SIGNALING_SERVER_URL}?role=agent&agentId=${AGENT_ID}`);
416
494
 
417
495
  ws.on('open', () => {
418
496
  logToFile('✅ Connected to signaling server.');
497
+
498
+ // Start heartbeat system to maintain agent status
499
+ startHeartbeatSystem();
419
500
  });
420
501
 
421
502
  ws.on('message', async (message) => {
@@ -689,6 +770,9 @@ async function createPeerConnection(clientId) {
689
770
  }
690
771
 
691
772
  function cleanup(clientId = null) {
773
+ // Stop heartbeat system
774
+ stopHeartbeatSystem();
775
+
692
776
  // Disconnect client from session manager
693
777
  if (clientId) {
694
778
  sessionManager.disconnectClient(clientId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shell-mirror",
3
- "version": "1.5.64",
3
+ "version": "1.5.65",
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": {