shell-mirror 1.5.41 → 1.5.43

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.
@@ -146,6 +146,12 @@ class SessionManager {
146
146
  });
147
147
  });
148
148
 
149
+ // Send initial prompt after terminal is ready
150
+ setTimeout(() => {
151
+ // Send a newline to trigger the shell prompt
152
+ terminal.write('\n');
153
+ }, 500);
154
+
149
155
  terminal.on('exit', (code) => {
150
156
  logToFile(`[SESSION] Terminal process exited for session ${sessionId} with code ${code}`);
151
157
  session.status = 'crashed';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shell-mirror",
3
- "version": "1.5.41",
3
+ "version": "1.5.43",
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": {
@@ -82,30 +82,8 @@ class ShellMirrorDashboard {
82
82
  if (agentsData.success && agentsData.data && agentsData.data.agents) {
83
83
  this.agents = agentsData.data.agents;
84
84
 
85
- // Simulate session data for each agent
86
- this.agents.forEach(agent => {
87
- if (agent.onlineStatus === 'online') {
88
- // Mock sessions for online agents
89
- this.agentSessions[agent.agentId] = [
90
- {
91
- id: `ses_${Date.now()}_main`,
92
- name: 'Main Terminal',
93
- lastActivity: Date.now() - 5 * 60 * 1000, // 5 minutes ago
94
- createdAt: Date.now() - 2 * 60 * 60 * 1000, // 2 hours ago
95
- status: 'active',
96
- connectedClients: 0
97
- },
98
- {
99
- id: `ses_${Date.now()}_debug`,
100
- name: 'Debug Server',
101
- lastActivity: Date.now() - 15 * 60 * 1000, // 15 minutes ago
102
- createdAt: Date.now() - 1 * 60 * 60 * 1000, // 1 hour ago
103
- status: 'active',
104
- connectedClients: 0
105
- }
106
- ];
107
- }
108
- });
85
+ // Load session data from localStorage (persisted from terminal connections)
86
+ this.loadSessionsFromStorage();
109
87
  }
110
88
 
111
89
  // TODO: Load session history when API is available
@@ -214,10 +192,10 @@ class ShellMirrorDashboard {
214
192
  </div>
215
193
  <div class="agent-actions">
216
194
  <button class="btn-connect" onclick="dashboard.connectToAgent('${agent.agentId}')">
217
- New Session
195
+ ${sessionCount > 0 ? 'Resume Session' : 'New Session'}
218
196
  </button>
219
197
  ${sessionCount > 0 ? `<button class="btn-sessions" onclick="dashboard.showAgentSessions('${agent.agentId}')">
220
- View Sessions
198
+ All Sessions
221
199
  </button>` : ''}
222
200
  </div>
223
201
  </div>
@@ -435,13 +413,40 @@ class ShellMirrorDashboard {
435
413
 
436
414
  // Action handlers
437
415
  async connectToAgent(agentId) {
438
- window.location.href = `/app/terminal.html?agent=${agentId}`;
416
+ console.log('[DASHBOARD] 🔍 DEBUG: connectToAgent called with agentId:', agentId);
417
+ console.log('[DASHBOARD] 🔍 DEBUG: Current agentSessions:', this.agentSessions);
418
+
419
+ // Check if there are existing sessions for this agent
420
+ const sessions = this.agentSessions[agentId] || [];
421
+ console.log('[DASHBOARD] 🔍 DEBUG: Sessions for agent:', sessions);
422
+
423
+ const activeSessions = sessions.filter(s => s.status === 'active');
424
+ console.log('[DASHBOARD] 🔍 DEBUG: Active sessions:', activeSessions);
425
+
426
+ if (activeSessions.length > 0) {
427
+ // Reconnect to the most recently active session
428
+ const mostRecentSession = activeSessions.reduce((latest, session) =>
429
+ session.lastActivity > latest.lastActivity ? session : latest
430
+ );
431
+ console.log(`[DASHBOARD] ✅ Reconnecting to existing session: ${mostRecentSession.id}`);
432
+ window.location.href = `/app/terminal.html?agent=${agentId}&session=${mostRecentSession.id}`;
433
+ } else {
434
+ // No existing sessions, create new one
435
+ console.log(`[DASHBOARD] 🆕 Creating new session for agent: ${agentId}`);
436
+ window.location.href = `/app/terminal.html?agent=${agentId}`;
437
+ }
439
438
  }
440
439
 
441
440
  async connectToSession(agentId, sessionId) {
442
441
  window.location.href = `/app/terminal.html?agent=${agentId}&session=${sessionId}`;
443
442
  }
444
443
 
444
+ async createNewSession(agentId) {
445
+ // Force creation of new session by not passing session parameter
446
+ console.log(`[DASHBOARD] Creating new session for agent: ${agentId}`);
447
+ window.location.href = `/app/terminal.html?agent=${agentId}`;
448
+ }
449
+
445
450
  startNewSession() {
446
451
  // Get first available agent for new session
447
452
  const activeAgents = this.agents.filter(agent => {
@@ -488,7 +493,7 @@ class ShellMirrorDashboard {
488
493
  ${sessionsList}
489
494
  </div>
490
495
  <div class="sessions-modal-actions">
491
- <button class="btn-primary" onclick="dashboard.connectToAgent('${agentId}')">
496
+ <button class="btn-primary" onclick="dashboard.createNewSession('${agentId}')">
492
497
  + Create New Session
493
498
  </button>
494
499
  </div>
@@ -530,6 +535,50 @@ class ShellMirrorDashboard {
530
535
  return `${days}d ago`;
531
536
  }
532
537
 
538
+ // Session storage management
539
+ loadSessionsFromStorage() {
540
+ try {
541
+ console.log('[DASHBOARD] 🔍 DEBUG: Loading sessions from localStorage');
542
+ const storedSessions = localStorage.getItem('shell-mirror-sessions');
543
+ console.log('[DASHBOARD] 🔍 DEBUG: Raw stored sessions:', storedSessions);
544
+
545
+ if (storedSessions) {
546
+ const sessionData = JSON.parse(storedSessions);
547
+ console.log('[DASHBOARD] 🔍 DEBUG: Parsed session data:', sessionData);
548
+
549
+ // Filter out old sessions (older than 24 hours)
550
+ const now = Date.now();
551
+ const maxAge = 24 * 60 * 60 * 1000; // 24 hours
552
+
553
+ Object.keys(sessionData).forEach(agentId => {
554
+ console.log('[DASHBOARD] 🔍 DEBUG: Processing agent:', agentId);
555
+ const allSessions = sessionData[agentId];
556
+ console.log('[DASHBOARD] 🔍 DEBUG: All sessions for agent:', allSessions);
557
+
558
+ const validSessions = allSessions.filter(session => {
559
+ const age = now - session.lastActivity;
560
+ const isValid = age < maxAge;
561
+ console.log('[DASHBOARD] 🔍 DEBUG: Session', session.id, 'age:', age, 'valid:', isValid);
562
+ return isValid;
563
+ });
564
+
565
+ console.log('[DASHBOARD] 🔍 DEBUG: Valid sessions for agent:', validSessions);
566
+
567
+ if (validSessions.length > 0) {
568
+ this.agentSessions[agentId] = validSessions;
569
+ }
570
+ });
571
+
572
+ console.log('[DASHBOARD] ✅ Loaded sessions from storage:', this.agentSessions);
573
+ } else {
574
+ console.log('[DASHBOARD] ⚠️ No stored sessions found in localStorage');
575
+ }
576
+ } catch (error) {
577
+ console.error('[DASHBOARD] ❌ Error loading sessions from storage:', error);
578
+ }
579
+ }
580
+
581
+
533
582
  showAgentInstructions() {
534
583
  // TODO: Show modal with agent setup instructions
535
584
  alert('Agent setup instructions coming soon!');
@@ -84,10 +84,14 @@ window.addEventListener('load', () => {
84
84
  const agentId = urlParams.get('agent');
85
85
  const sessionId = urlParams.get('session');
86
86
 
87
+ console.log('[CLIENT] 🔍 DEBUG: URL params - agent:', agentId, 'session:', sessionId);
88
+ console.log('[CLIENT] 🔍 DEBUG: Full URL:', window.location.href);
89
+
87
90
  if (agentId) {
88
91
  AGENT_ID = agentId;
89
92
  SELECTED_AGENT = { id: agentId, agentId: agentId };
90
93
  requestedSessionId = sessionId; // Store for session request
94
+ console.log('[CLIENT] 🔍 DEBUG: Set requestedSessionId to:', requestedSessionId);
91
95
  console.log('[CLIENT] 🔗 Connecting to agent:', agentId, sessionId ? `session: ${sessionId}` : '(new session)');
92
96
  startConnection();
93
97
  } else {
@@ -174,6 +178,8 @@ async function initialize() {
174
178
 
175
179
  // Build session request
176
180
  let sessionRequest = null;
181
+ console.log('[CLIENT] 🔍 DEBUG: Building session request, requestedSessionId:', requestedSessionId);
182
+
177
183
  if (requestedSessionId) {
178
184
  sessionRequest = { sessionId: requestedSessionId };
179
185
  console.log(`[CLIENT] 🎯 Requesting existing session: ${requestedSessionId}`);
@@ -221,9 +227,13 @@ async function initialize() {
221
227
  isNewSession: nextData.isNewSession || false
222
228
  };
223
229
  console.log('[CLIENT] 📋 Session assigned:', currentSession);
230
+ console.log('[CLIENT] 🔍 Agent ID for storage:', AGENT_ID);
224
231
 
225
232
  // Update UI to show session info
226
233
  updateSessionDisplay();
234
+
235
+ // Save session info to localStorage for dashboard
236
+ saveSessionToLocalStorage(AGENT_ID, currentSession);
227
237
  }
228
238
 
229
239
  if (nextData.availableSessions) {
@@ -679,6 +689,9 @@ function handleSessionMessage(message) {
679
689
  updateSessionDisplay();
680
690
  term.clear(); // Clear terminal for new session
681
691
  console.log('[CLIENT] ✅ Switched to session:', currentSession);
692
+
693
+ // Save updated session info
694
+ saveSessionToLocalStorage(AGENT_ID, currentSession);
682
695
  break;
683
696
  case 'session-ended':
684
697
  term.write(`\r\n\x1b[31m❌ Session ended: ${message.reason}\x1b[0m\r\n`);
@@ -694,4 +707,46 @@ function handleSessionMessage(message) {
694
707
  term.write(`\r\n\x1b[31m❌ Error: ${message.message}\x1b[0m\r\n`);
695
708
  break;
696
709
  }
710
+ }
711
+
712
+ // Session storage helper
713
+ function saveSessionToLocalStorage(agentId, sessionInfo) {
714
+ try {
715
+ console.log('[CLIENT] 🔍 DEBUG: Saving session to localStorage');
716
+ console.log('[CLIENT] 🔍 DEBUG: AgentID:', agentId);
717
+ console.log('[CLIENT] 🔍 DEBUG: SessionInfo:', sessionInfo);
718
+
719
+ const storedSessions = localStorage.getItem('shell-mirror-sessions');
720
+ console.log('[CLIENT] 🔍 DEBUG: Current stored sessions:', storedSessions);
721
+
722
+ let sessionData = storedSessions ? JSON.parse(storedSessions) : {};
723
+
724
+ if (!sessionData[agentId]) {
725
+ sessionData[agentId] = [];
726
+ }
727
+
728
+ // Remove existing session with same ID
729
+ sessionData[agentId] = sessionData[agentId].filter(s => s.id !== sessionInfo.id);
730
+
731
+ // Add updated session info
732
+ const sessionToStore = {
733
+ id: sessionInfo.id,
734
+ name: sessionInfo.name,
735
+ lastActivity: Date.now(),
736
+ createdAt: sessionInfo.createdAt || Date.now(),
737
+ status: 'active'
738
+ };
739
+
740
+ sessionData[agentId].push(sessionToStore);
741
+
742
+ localStorage.setItem('shell-mirror-sessions', JSON.stringify(sessionData));
743
+ console.log('[CLIENT] 💾 Session saved to storage:', sessionToStore);
744
+ console.log('[CLIENT] 🔍 DEBUG: Final stored data:', JSON.stringify(sessionData));
745
+
746
+ // Verify the save worked
747
+ const verification = localStorage.getItem('shell-mirror-sessions');
748
+ console.log('[CLIENT] ✅ DEBUG: Verification read:', verification);
749
+ } catch (error) {
750
+ console.error('[CLIENT] ❌ Error saving session to storage:', error);
751
+ }
697
752
  }