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 +1 -1
- package/public/app/terminal.html +15 -0
- package/public/app/terminal.js +32 -26
package/package.json
CHANGED
package/public/app/terminal.html
CHANGED
|
@@ -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
|
}
|
package/public/app/terminal.js
CHANGED
|
@@ -274,7 +274,7 @@ function startConnection() {
|
|
|
274
274
|
term.open(document.getElementById('terminal'));
|
|
275
275
|
|
|
276
276
|
// Show initial connection message
|
|
277
|
-
setConnectionMessage('
|
|
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('
|
|
302
|
-
term.write('\r\n\x1b[
|
|
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('
|
|
309
|
-
term.write('\x1b[
|
|
310
|
-
term.write('\x1b[
|
|
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('
|
|
318
|
-
term.write('\r\n\r\n\x1b[
|
|
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[
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
874
|
-
term.write('\r\n\r\
|
|
875
|
-
term.write('
|
|
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[
|
|
977
|
-
term.write('
|
|
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[
|
|
984
|
-
term.write('
|
|
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[
|
|
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[
|
|
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[
|
|
1362
|
-
term.write('
|
|
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[
|
|
1380
|
+
term.write(`\r\n\x1b[31mError: ${message.message}\x1b[0m\r\n`);
|
|
1375
1381
|
break;
|
|
1376
1382
|
}
|
|
1377
1383
|
}
|