shell-mirror 1.5.41 → 1.5.42

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.42",
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,34 @@ class ShellMirrorDashboard {
435
413
 
436
414
  // Action handlers
437
415
  async connectToAgent(agentId) {
438
- window.location.href = `/app/terminal.html?agent=${agentId}`;
416
+ // Check if there are existing sessions for this agent
417
+ const sessions = this.agentSessions[agentId] || [];
418
+ const activeSessions = sessions.filter(s => s.status === 'active');
419
+
420
+ if (activeSessions.length > 0) {
421
+ // Reconnect to the most recently active session
422
+ const mostRecentSession = activeSessions.reduce((latest, session) =>
423
+ session.lastActivity > latest.lastActivity ? session : latest
424
+ );
425
+ console.log(`[DASHBOARD] Reconnecting to existing session: ${mostRecentSession.id}`);
426
+ window.location.href = `/app/terminal.html?agent=${agentId}&session=${mostRecentSession.id}`;
427
+ } else {
428
+ // No existing sessions, create new one
429
+ console.log(`[DASHBOARD] Creating new session for agent: ${agentId}`);
430
+ window.location.href = `/app/terminal.html?agent=${agentId}`;
431
+ }
439
432
  }
440
433
 
441
434
  async connectToSession(agentId, sessionId) {
442
435
  window.location.href = `/app/terminal.html?agent=${agentId}&session=${sessionId}`;
443
436
  }
444
437
 
438
+ async createNewSession(agentId) {
439
+ // Force creation of new session by not passing session parameter
440
+ console.log(`[DASHBOARD] Creating new session for agent: ${agentId}`);
441
+ window.location.href = `/app/terminal.html?agent=${agentId}`;
442
+ }
443
+
445
444
  startNewSession() {
446
445
  // Get first available agent for new session
447
446
  const activeAgents = this.agents.filter(agent => {
@@ -488,7 +487,7 @@ class ShellMirrorDashboard {
488
487
  ${sessionsList}
489
488
  </div>
490
489
  <div class="sessions-modal-actions">
491
- <button class="btn-primary" onclick="dashboard.connectToAgent('${agentId}')">
490
+ <button class="btn-primary" onclick="dashboard.createNewSession('${agentId}')">
492
491
  + Create New Session
493
492
  </button>
494
493
  </div>
@@ -530,6 +529,35 @@ class ShellMirrorDashboard {
530
529
  return `${days}d ago`;
531
530
  }
532
531
 
532
+ // Session storage management
533
+ loadSessionsFromStorage() {
534
+ try {
535
+ const storedSessions = localStorage.getItem('shell-mirror-sessions');
536
+ if (storedSessions) {
537
+ const sessionData = JSON.parse(storedSessions);
538
+
539
+ // Filter out old sessions (older than 24 hours)
540
+ const now = Date.now();
541
+ const maxAge = 24 * 60 * 60 * 1000; // 24 hours
542
+
543
+ Object.keys(sessionData).forEach(agentId => {
544
+ const validSessions = sessionData[agentId].filter(session =>
545
+ (now - session.lastActivity) < maxAge
546
+ );
547
+
548
+ if (validSessions.length > 0) {
549
+ this.agentSessions[agentId] = validSessions;
550
+ }
551
+ });
552
+
553
+ console.log('[DASHBOARD] Loaded sessions from storage:', this.agentSessions);
554
+ }
555
+ } catch (error) {
556
+ console.error('[DASHBOARD] Error loading sessions from storage:', error);
557
+ }
558
+ }
559
+
560
+
533
561
  showAgentInstructions() {
534
562
  // TODO: Show modal with agent setup instructions
535
563
  alert('Agent setup instructions coming soon!');
@@ -224,6 +224,9 @@ async function initialize() {
224
224
 
225
225
  // Update UI to show session info
226
226
  updateSessionDisplay();
227
+
228
+ // Save session info to localStorage for dashboard
229
+ saveSessionToLocalStorage(AGENT_ID, currentSession);
227
230
  }
228
231
 
229
232
  if (nextData.availableSessions) {
@@ -679,6 +682,9 @@ function handleSessionMessage(message) {
679
682
  updateSessionDisplay();
680
683
  term.clear(); // Clear terminal for new session
681
684
  console.log('[CLIENT] ✅ Switched to session:', currentSession);
685
+
686
+ // Save updated session info
687
+ saveSessionToLocalStorage(AGENT_ID, currentSession);
682
688
  break;
683
689
  case 'session-ended':
684
690
  term.write(`\r\n\x1b[31m❌ Session ended: ${message.reason}\x1b[0m\r\n`);
@@ -694,4 +700,33 @@ function handleSessionMessage(message) {
694
700
  term.write(`\r\n\x1b[31m❌ Error: ${message.message}\x1b[0m\r\n`);
695
701
  break;
696
702
  }
703
+ }
704
+
705
+ // Session storage helper
706
+ function saveSessionToLocalStorage(agentId, sessionInfo) {
707
+ try {
708
+ const storedSessions = localStorage.getItem('shell-mirror-sessions');
709
+ let sessionData = storedSessions ? JSON.parse(storedSessions) : {};
710
+
711
+ if (!sessionData[agentId]) {
712
+ sessionData[agentId] = [];
713
+ }
714
+
715
+ // Remove existing session with same ID
716
+ sessionData[agentId] = sessionData[agentId].filter(s => s.id !== sessionInfo.id);
717
+
718
+ // Add updated session info
719
+ sessionData[agentId].push({
720
+ id: sessionInfo.id,
721
+ name: sessionInfo.name,
722
+ lastActivity: Date.now(),
723
+ createdAt: sessionInfo.createdAt || Date.now(),
724
+ status: 'active'
725
+ });
726
+
727
+ localStorage.setItem('shell-mirror-sessions', JSON.stringify(sessionData));
728
+ console.log('[CLIENT] 💾 Session saved to storage:', sessionInfo);
729
+ } catch (error) {
730
+ console.error('[CLIENT] Error saving session to storage:', error);
731
+ }
697
732
  }