shell-mirror 1.5.22 → 1.5.24
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/lib/auto-start.js +63 -56
- package/package.json +1 -1
- package/public/app/terminal-http.html +92 -0
- package/public/app/terminal.js +3 -10
package/lib/auto-start.js
CHANGED
|
@@ -445,68 +445,25 @@ WS_URL=${wsConfig.wsUrl}` : ''}
|
|
|
445
445
|
|
|
446
446
|
async startAuthenticatedServer(authInfo) {
|
|
447
447
|
console.log('');
|
|
448
|
-
console.log('🚀 Starting authenticated Shell Mirror with
|
|
448
|
+
console.log('🚀 Starting authenticated Shell Mirror with cloud WebSocket connection...');
|
|
449
449
|
|
|
450
450
|
try {
|
|
451
|
-
//
|
|
452
|
-
|
|
453
|
-
const wsConfig = NetworkUtils.generateWebSocketConfig(wsPort);
|
|
451
|
+
// Register this agent with the cloud backend
|
|
452
|
+
await this.registerAsMacAgent(authInfo);
|
|
454
453
|
|
|
455
|
-
//
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
// Create .env file with authentication and WebSocket config
|
|
459
|
-
await this.createEnvFile(authInfo, wsConfig);
|
|
460
|
-
|
|
461
|
-
// Register this server as a Mac agent with WebSocket endpoint
|
|
462
|
-
await this.registerAsMacAgent(authInfo, wsConfig);
|
|
463
|
-
|
|
464
|
-
// Start the local WebSocket server process
|
|
465
|
-
const packageRoot = path.resolve(__dirname, '..');
|
|
466
|
-
const serverPath = path.join(packageRoot, 'server.js');
|
|
467
|
-
|
|
468
|
-
console.log('🔄 Starting local WebSocket server...');
|
|
469
|
-
const serverProcess = spawn('node', [serverPath], {
|
|
470
|
-
stdio: 'inherit',
|
|
471
|
-
cwd: path.dirname(this.envFile),
|
|
472
|
-
env: {
|
|
473
|
-
...process.env,
|
|
474
|
-
WS_PORT: wsConfig.port.toString(),
|
|
475
|
-
WS_HOST: wsConfig.host,
|
|
476
|
-
LOCAL_IP: wsConfig.localIP
|
|
477
|
-
}
|
|
478
|
-
});
|
|
479
|
-
|
|
480
|
-
// Display status information
|
|
481
|
-
this.displayStatus(authInfo, wsConfig);
|
|
482
|
-
|
|
483
|
-
// Handle Ctrl+C gracefully
|
|
484
|
-
process.on('SIGINT', () => {
|
|
485
|
-
console.log('');
|
|
486
|
-
console.log('🛑 Stopping Shell Mirror and WebSocket server...');
|
|
487
|
-
serverProcess.kill('SIGINT');
|
|
488
|
-
process.exit(0);
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
// Wait for server process
|
|
492
|
-
serverProcess.on('close', (code) => {
|
|
493
|
-
if (code !== 0) {
|
|
494
|
-
console.error(`❌ Server exited with code ${code}`);
|
|
495
|
-
process.exit(code);
|
|
496
|
-
}
|
|
497
|
-
});
|
|
454
|
+
// Start the terminal agent with cloud WebSocket connection
|
|
455
|
+
await this.startTerminalAgent(authInfo);
|
|
498
456
|
|
|
499
457
|
} catch (error) {
|
|
500
|
-
console.error('❌ Failed to start
|
|
458
|
+
console.error('❌ Failed to start Shell Mirror:', error.message);
|
|
501
459
|
process.exit(1);
|
|
502
460
|
}
|
|
503
461
|
}
|
|
504
462
|
|
|
505
|
-
async registerAsMacAgent(authInfo
|
|
506
|
-
console.log('🔗 Registering as Mac agent with WebSocket
|
|
463
|
+
async registerAsMacAgent(authInfo) {
|
|
464
|
+
console.log('🔗 Registering as Mac agent with cloud WebSocket...');
|
|
507
465
|
console.log(` User: ${authInfo.email}`);
|
|
508
466
|
console.log(` Machine: ${os.hostname()}`);
|
|
509
|
-
console.log(` WebSocket: ${wsConfig.wsUrl}`);
|
|
510
467
|
|
|
511
468
|
try {
|
|
512
469
|
const agentId = `local-${os.hostname()}-${Date.now()}`;
|
|
@@ -516,11 +473,9 @@ WS_URL=${wsConfig.wsUrl}` : ''}
|
|
|
516
473
|
ownerName: authInfo.name,
|
|
517
474
|
ownerToken: authInfo.accessToken,
|
|
518
475
|
machineName: os.hostname(),
|
|
519
|
-
agentVersion: '1.5.
|
|
520
|
-
capabilities: ['terminal', 'websocket'],
|
|
521
|
-
|
|
522
|
-
websocketUrl: wsConfig.wsUrl,
|
|
523
|
-
localIP: wsConfig.localIP
|
|
476
|
+
agentVersion: '1.5.23',
|
|
477
|
+
capabilities: ['terminal', 'cloud-websocket'],
|
|
478
|
+
connectionType: 'cloud-websocket'
|
|
524
479
|
};
|
|
525
480
|
|
|
526
481
|
console.log(` Agent ID: ${agentId}`);
|
|
@@ -577,6 +532,58 @@ WS_URL=${wsConfig.wsUrl}` : ''}
|
|
|
577
532
|
}
|
|
578
533
|
}
|
|
579
534
|
|
|
535
|
+
async startTerminalAgent(authInfo) {
|
|
536
|
+
console.log('');
|
|
537
|
+
console.log('🔄 Starting terminal agent with cloud WebSocket connection...');
|
|
538
|
+
|
|
539
|
+
// Find the package root directory (where agent files are located)
|
|
540
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
541
|
+
const agentPath = path.join(packageRoot, 'mac-agent', 'agent.js');
|
|
542
|
+
|
|
543
|
+
// Create environment for agent
|
|
544
|
+
const agentEnv = {
|
|
545
|
+
...process.env,
|
|
546
|
+
USER_EMAIL: authInfo.email,
|
|
547
|
+
USER_NAME: authInfo.name,
|
|
548
|
+
ACCESS_TOKEN: authInfo.accessToken,
|
|
549
|
+
WEBSOCKET_URL: 'wss://shellmirror.app',
|
|
550
|
+
CONNECTION_TYPE: 'cloud-websocket'
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
console.log('🌐 Connecting to: wss://shellmirror.app');
|
|
554
|
+
console.log('📱 Access from browser: https://shellmirror.app/app/terminal.html');
|
|
555
|
+
console.log('');
|
|
556
|
+
|
|
557
|
+
// Start the terminal agent process
|
|
558
|
+
const agentProcess = spawn('node', [agentPath], {
|
|
559
|
+
stdio: 'inherit',
|
|
560
|
+
env: agentEnv
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
// Display final status
|
|
564
|
+
const pkg = require('../package.json');
|
|
565
|
+
console.log(`✅ Shell Mirror v${pkg.version} - Running (${authInfo.email})`);
|
|
566
|
+
console.log('🌐 Connection: Cloud WebSocket (wss://shellmirror.app)');
|
|
567
|
+
console.log('Press Ctrl+C to stop');
|
|
568
|
+
console.log('');
|
|
569
|
+
|
|
570
|
+
// Handle Ctrl+C gracefully
|
|
571
|
+
process.on('SIGINT', () => {
|
|
572
|
+
console.log('');
|
|
573
|
+
console.log('🛑 Stopping Shell Mirror agent...');
|
|
574
|
+
agentProcess.kill('SIGINT');
|
|
575
|
+
process.exit(0);
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
// Wait for agent process
|
|
579
|
+
agentProcess.on('close', (code) => {
|
|
580
|
+
if (code !== 0) {
|
|
581
|
+
console.error(`❌ Agent exited with code ${code}`);
|
|
582
|
+
process.exit(code);
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
|
|
580
587
|
async makeHttpsRequest(options, postData = null) {
|
|
581
588
|
return new Promise((resolve, reject) => {
|
|
582
589
|
const req = https.request(options, (res) => {
|
package/package.json
CHANGED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Terminal Mirror (HTTP)</title>
|
|
5
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@4.15.0/css/xterm.css" />
|
|
6
|
+
<script src="https://cdn.jsdelivr.net/npm/xterm@4.15.0/lib/xterm.js"></script>
|
|
7
|
+
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.js"></script>
|
|
8
|
+
<style>
|
|
9
|
+
body, html {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
height: 100%;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
background-color: #1e1e1e;
|
|
15
|
+
color: #ccc;
|
|
16
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
17
|
+
}
|
|
18
|
+
#terminal-container {
|
|
19
|
+
display: none;
|
|
20
|
+
height: 100%;
|
|
21
|
+
width: 100%;
|
|
22
|
+
background-color: #000000;
|
|
23
|
+
}
|
|
24
|
+
#terminal {
|
|
25
|
+
padding: 8px; /* Mac Terminal.app padding */
|
|
26
|
+
background-color: #000000;
|
|
27
|
+
height: calc(100% - 16px);
|
|
28
|
+
width: calc(100% - 16px);
|
|
29
|
+
}
|
|
30
|
+
#connect-container {
|
|
31
|
+
padding: 2em;
|
|
32
|
+
text-align: center;
|
|
33
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
34
|
+
color: white;
|
|
35
|
+
min-height: 100vh;
|
|
36
|
+
}
|
|
37
|
+
#connect-container h2 {
|
|
38
|
+
margin-bottom: 2em;
|
|
39
|
+
font-size: 2.5rem;
|
|
40
|
+
}
|
|
41
|
+
.http-notice {
|
|
42
|
+
background: rgba(255, 255, 255, 0.1);
|
|
43
|
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
44
|
+
border-radius: 10px;
|
|
45
|
+
padding: 20px;
|
|
46
|
+
margin: 20px auto;
|
|
47
|
+
max-width: 600px;
|
|
48
|
+
}
|
|
49
|
+
.http-notice h3 {
|
|
50
|
+
color: #4CAF50;
|
|
51
|
+
margin-bottom: 10px;
|
|
52
|
+
}
|
|
53
|
+
#agent-id-input { font-size: 1.2em; padding: 8px; width: 400px; margin-bottom: 1em; }
|
|
54
|
+
#connect-btn { font-size: 1.2em; padding: 10px 20px; }
|
|
55
|
+
</style>
|
|
56
|
+
</head>
|
|
57
|
+
<body>
|
|
58
|
+
<div id="connect-container">
|
|
59
|
+
<h2>Terminal Mirror</h2>
|
|
60
|
+
|
|
61
|
+
<div class="http-notice">
|
|
62
|
+
<h3>🌐 HTTP Terminal Mode</h3>
|
|
63
|
+
<p>This HTTP version allows secure connections to your local Mac WebSocket server.</p>
|
|
64
|
+
<p>Perfect for local network terminal access!</p>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div id="agent-discovery">
|
|
68
|
+
<p>Discovering available Mac agents...</p>
|
|
69
|
+
<div id="agent-list"></div>
|
|
70
|
+
</div>
|
|
71
|
+
<div id="manual-connect" style="display: none; margin-top: 20px;">
|
|
72
|
+
<p>Or manually enter Agent ID:</p>
|
|
73
|
+
<input type="text" id="agent-id-input" placeholder="e.g., agent-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
|
|
74
|
+
<br>
|
|
75
|
+
<button id="connect-btn">Connect</button>
|
|
76
|
+
</div>
|
|
77
|
+
<button id="show-manual" style="margin-top: 10px;">Manual Connect</button>
|
|
78
|
+
</div>
|
|
79
|
+
<div id="terminal-container">
|
|
80
|
+
<div id="terminal"></div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<!-- Version Footer -->
|
|
84
|
+
<footer style="background: #ff6b35; color: white; text-align: center; padding: 10px 0; font-size: 0.8rem; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000;">
|
|
85
|
+
<div style="max-width: 1200px; margin: 0 auto;">
|
|
86
|
+
<p id="terminal-version-info">Terminal Mirror (HTTP) • Loading version...</p>
|
|
87
|
+
</div>
|
|
88
|
+
</footer>
|
|
89
|
+
|
|
90
|
+
<script src="/app/terminal.js"></script>
|
|
91
|
+
</body>
|
|
92
|
+
</html>
|
package/public/app/terminal.js
CHANGED
|
@@ -228,16 +228,9 @@ async function initialize() {
|
|
|
228
228
|
console.log('[CLIENT] 🚀 Initializing WebRTC connection to agent:', AGENT_ID);
|
|
229
229
|
console.log('[CLIENT] 📋 Selected agent data:', SELECTED_AGENT);
|
|
230
230
|
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
signalingUrl = SELECTED_AGENT.websocketUrl;
|
|
235
|
-
console.log('[CLIENT] 🌐 Using agent\'s local WebSocket server:', signalingUrl);
|
|
236
|
-
} else {
|
|
237
|
-
// Fallback to web app domain (old behavior)
|
|
238
|
-
signalingUrl = (window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host;
|
|
239
|
-
console.log('[CLIENT] 🌐 Using fallback WebSocket server:', signalingUrl);
|
|
240
|
-
}
|
|
231
|
+
// Use cloud WebSocket for all connections (solves HTTPS mixed content issue)
|
|
232
|
+
const signalingUrl = (window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host;
|
|
233
|
+
console.log('[CLIENT] 🌐 Using cloud WebSocket server:', signalingUrl);
|
|
241
234
|
|
|
242
235
|
ws = new WebSocket(`${signalingUrl}?role=client`);
|
|
243
236
|
|