shell-mirror 1.5.123 → 1.5.125
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 +1 -1
- package/public/app/terminal.js +82 -13
package/package.json
CHANGED
package/public/app/terminal.html
CHANGED
|
@@ -363,7 +363,7 @@
|
|
|
363
363
|
<p>Connecting to terminal...</p>
|
|
364
364
|
</div>
|
|
365
365
|
<div id="terminal-container">
|
|
366
|
-
<div class="session-header" id="session-header"
|
|
366
|
+
<div class="session-header" id="session-header">
|
|
367
367
|
<!-- Connection Status Indicator -->
|
|
368
368
|
<div class="connection-status" id="connection-status"></div>
|
|
369
369
|
|
package/public/app/terminal.js
CHANGED
|
@@ -56,6 +56,10 @@ let currentSession = null;
|
|
|
56
56
|
let availableSessions = [];
|
|
57
57
|
let requestedSessionId = null; // For connecting to specific session from URL
|
|
58
58
|
|
|
59
|
+
// Connection status messaging
|
|
60
|
+
let connectionStatusMessage = 'Connecting to agent...';
|
|
61
|
+
let connectionTimeoutWarning = null;
|
|
62
|
+
|
|
59
63
|
// Chunk reassembly for large messages
|
|
60
64
|
const chunkAssembler = {
|
|
61
65
|
activeChunks: new Map(),
|
|
@@ -166,6 +170,30 @@ function updateConnectionStatus(status) {
|
|
|
166
170
|
// else: disconnected (default red)
|
|
167
171
|
}
|
|
168
172
|
|
|
173
|
+
// Set connection status message (shown in tab bar when no sessions)
|
|
174
|
+
function setConnectionMessage(message, writeToTerminal = true) {
|
|
175
|
+
connectionStatusMessage = message;
|
|
176
|
+
console.log('[CLIENT] 📢 Connection message:', message);
|
|
177
|
+
|
|
178
|
+
// Update the tab bar display
|
|
179
|
+
updateSessionDisplay();
|
|
180
|
+
|
|
181
|
+
// Optionally write to terminal for visibility
|
|
182
|
+
if (writeToTerminal && term) {
|
|
183
|
+
term.write(`\r\n\x1b[36m${message}\x1b[0m\r\n`); // Cyan color
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Clear connection timeout warnings (called when connection succeeds)
|
|
188
|
+
function clearConnectionTimeouts() {
|
|
189
|
+
if (connectionTimeoutWarning) {
|
|
190
|
+
clearTimeout(connectionTimeoutWarning.timeout10s);
|
|
191
|
+
clearTimeout(connectionTimeoutWarning.timeout30s);
|
|
192
|
+
connectionTimeoutWarning = null;
|
|
193
|
+
console.log('[CLIENT] ✅ Connection timeout warnings cleared');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
169
197
|
// Cleanup timer for chunk assembler
|
|
170
198
|
setInterval(() => {
|
|
171
199
|
chunkAssembler.cleanup();
|
|
@@ -243,7 +271,13 @@ function startConnection() {
|
|
|
243
271
|
connectContainer.style.display = 'none';
|
|
244
272
|
terminalContainer.classList.add('show');
|
|
245
273
|
term.open(document.getElementById('terminal'));
|
|
246
|
-
|
|
274
|
+
|
|
275
|
+
// Show initial connection message
|
|
276
|
+
setConnectionMessage('🔗 Connecting to agent...', true);
|
|
277
|
+
|
|
278
|
+
// Initialize session display (shows header with connection status even before session exists)
|
|
279
|
+
updateSessionDisplay();
|
|
280
|
+
|
|
247
281
|
// Track terminal session start in Google Analytics
|
|
248
282
|
if (typeof sendGAEvent === 'function') {
|
|
249
283
|
sendGAEvent('terminal_session_start', {
|
|
@@ -259,6 +293,26 @@ function startConnection() {
|
|
|
259
293
|
fitAddon.fit();
|
|
260
294
|
term.focus(); // Ensure cursor is visible even before connection
|
|
261
295
|
}, 100);
|
|
296
|
+
|
|
297
|
+
// Set up connection timeout warnings
|
|
298
|
+
const timeout10s = setTimeout(() => {
|
|
299
|
+
if (!currentSession) {
|
|
300
|
+
setConnectionMessage('⏱️ Taking longer than usual... Please wait', true);
|
|
301
|
+
term.write('\r\n\x1b[33m⏱️ Connection is taking longer than expected...\x1b[0m\r\n');
|
|
302
|
+
}
|
|
303
|
+
}, 10000);
|
|
304
|
+
|
|
305
|
+
const timeout30s = setTimeout(() => {
|
|
306
|
+
if (!currentSession) {
|
|
307
|
+
setConnectionMessage('⚠️ Connection very slow - Agent may be offline', true);
|
|
308
|
+
term.write('\x1b[33m⚠️ Still trying to connect. The agent may be offline or unreachable.\x1b[0m\r\n');
|
|
309
|
+
term.write('\x1b[36m💡 Tip: Check the agent status on the Dashboard\x1b[0m\r\n');
|
|
310
|
+
}
|
|
311
|
+
}, 30000);
|
|
312
|
+
|
|
313
|
+
// Store timeout IDs so they can be cleared on successful connection
|
|
314
|
+
connectionTimeoutWarning = { timeout10s, timeout30s };
|
|
315
|
+
|
|
262
316
|
initialize();
|
|
263
317
|
}
|
|
264
318
|
|
|
@@ -272,17 +326,20 @@ async function initialize() {
|
|
|
272
326
|
|
|
273
327
|
if (directConnectionSuccess) {
|
|
274
328
|
console.log('[CLIENT] ✅ Direct connection established - no server needed!');
|
|
329
|
+
setConnectionMessage('✅ Connected via local network!', true);
|
|
275
330
|
return;
|
|
276
331
|
}
|
|
277
|
-
|
|
332
|
+
|
|
278
333
|
console.log('[CLIENT] ⚠️ Direct connection failed, falling back to WebRTC signaling...');
|
|
334
|
+
setConnectionMessage('🌐 Attempting WebRTC connection...', true);
|
|
279
335
|
await initializeWebRTCSignaling();
|
|
280
336
|
}
|
|
281
337
|
|
|
282
338
|
async function tryDirectConnection() {
|
|
283
339
|
console.log('[CLIENT] 🔗 Attempting direct connection to agent...');
|
|
284
340
|
updateConnectionStatus('connecting');
|
|
285
|
-
|
|
341
|
+
setConnectionMessage('🔍 Trying direct connection to local network...', true);
|
|
342
|
+
|
|
286
343
|
// Get agent data from API to find local connection details
|
|
287
344
|
try {
|
|
288
345
|
const response = await fetch('/php-backend/api/agents-list.php', {
|
|
@@ -391,6 +448,10 @@ function setupDirectConnection(directWs) {
|
|
|
391
448
|
case 'session_created':
|
|
392
449
|
console.log('[CLIENT] ✅ Direct session created:', data.sessionId);
|
|
393
450
|
|
|
451
|
+
// Clear connection timeout warnings
|
|
452
|
+
clearConnectionTimeouts();
|
|
453
|
+
setConnectionMessage('✅ Session created successfully!', false);
|
|
454
|
+
|
|
394
455
|
// Update current session
|
|
395
456
|
currentSession = {
|
|
396
457
|
id: data.sessionId,
|
|
@@ -567,6 +628,10 @@ async function initializeWebRTCSignaling() {
|
|
|
567
628
|
|
|
568
629
|
// Handle session assignment from agent
|
|
569
630
|
if (nextData.sessionId) {
|
|
631
|
+
// Clear connection timeout warnings
|
|
632
|
+
clearConnectionTimeouts();
|
|
633
|
+
setConnectionMessage('✅ Session connected!', false);
|
|
634
|
+
|
|
570
635
|
currentSession = {
|
|
571
636
|
id: nextData.sessionId,
|
|
572
637
|
name: nextData.sessionName || 'Terminal Session',
|
|
@@ -574,7 +639,7 @@ async function initializeWebRTCSignaling() {
|
|
|
574
639
|
};
|
|
575
640
|
console.log('[CLIENT] 📋 Session assigned:', currentSession);
|
|
576
641
|
console.log('[CLIENT] 🔍 Agent ID for storage:', AGENT_ID);
|
|
577
|
-
|
|
642
|
+
|
|
578
643
|
// Update UI to show session info
|
|
579
644
|
updateSessionDisplay();
|
|
580
645
|
|
|
@@ -790,6 +855,7 @@ async function createPeerConnection() {
|
|
|
790
855
|
console.log('[CLIENT] ❌ ICE connection failed - no viable candidates');
|
|
791
856
|
console.log('[CLIENT] 💡 Troubleshooting: This may be due to firewall/NAT issues or blocked STUN servers');
|
|
792
857
|
updateConnectionStatus('disconnected');
|
|
858
|
+
setConnectionMessage('❌ Unable to connect - Agent may be offline', false);
|
|
793
859
|
term.write('\r\n\r\n❌ Connection failed: Network connectivity issues\r\n');
|
|
794
860
|
term.write('💡 This may be due to:\r\n');
|
|
795
861
|
term.write(' • Firewall blocking WebRTC traffic\r\n');
|
|
@@ -955,14 +1021,14 @@ function updateSessionDisplay() {
|
|
|
955
1021
|
return;
|
|
956
1022
|
}
|
|
957
1023
|
|
|
958
|
-
if
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
// Update tabs
|
|
962
|
-
console.log('[CLIENT] 📋 Rendering tabs, availableSessions:', availableSessions);
|
|
963
|
-
renderTabs();
|
|
1024
|
+
// Always render tabs (they will show appropriate state even if no sessions)
|
|
1025
|
+
console.log('[CLIENT] 📋 Rendering tabs, availableSessions:', availableSessions, 'currentSession:', currentSession);
|
|
1026
|
+
renderTabs();
|
|
964
1027
|
|
|
1028
|
+
if (currentSession) {
|
|
965
1029
|
console.log('[CLIENT] 📋 Session display updated:', currentSession);
|
|
1030
|
+
} else {
|
|
1031
|
+
console.log('[CLIENT] 📋 No current session - showing connection state only');
|
|
966
1032
|
}
|
|
967
1033
|
}
|
|
968
1034
|
|
|
@@ -1036,10 +1102,13 @@ function renderTabs() {
|
|
|
1036
1102
|
</div>
|
|
1037
1103
|
`;
|
|
1038
1104
|
}).join('');
|
|
1039
|
-
}
|
|
1040
1105
|
|
|
1041
|
-
|
|
1042
|
-
|
|
1106
|
+
// Add new session button only when we have sessions
|
|
1107
|
+
tabsHTML += '<button class="session-tab-new" onclick="createNewSession()" title="New Session">+</button>';
|
|
1108
|
+
} else {
|
|
1109
|
+
// No sessions - show connection status message
|
|
1110
|
+
tabsHTML = `<div style="color: #888; font-size: 0.85rem; padding: 6px 12px;">${connectionStatusMessage}</div>`;
|
|
1111
|
+
}
|
|
1043
1112
|
|
|
1044
1113
|
tabBar.innerHTML = tabsHTML;
|
|
1045
1114
|
console.log('[CLIENT] ✅ Tabs rendered:', sessionsToRender.length, 'tabs');
|