/** * Test script for multi-user Chrome extension to LiveKit agent integration * This script simulates multiple Chrome extension connections and verifies * that LiveKit agents are automatically started for each user */ import WebSocket from 'ws'; const SERVER_URL = 'ws://localhost:3001/chrome'; const NUM_USERS = 3; class TestChromeUser { constructor(userId) { this.userId = userId; this.ws = null; this.sessionInfo = null; this.connected = false; this.liveKitAgentStarted = false; } async connect() { return new Promise((resolve, reject) => { console.log(`๐Ÿ‘ค User ${this.userId}: Connecting Chrome extension...`); this.ws = new WebSocket(SERVER_URL); this.ws.on('open', () => { console.log(`โœ… User ${this.userId}: Chrome extension connected`); this.connected = true; // Send connection info (simulating Chrome extension) const connectionInfo = { type: 'connection_info', userAgent: `TestChromeUser-${this.userId}`, timestamp: Date.now(), extensionId: `test-extension-${this.userId}` }; this.ws.send(JSON.stringify(connectionInfo)); }); this.ws.on('message', (data) => { try { const message = JSON.parse(data.toString()); if (message.type === 'session_info') { this.sessionInfo = message.sessionInfo; console.log(`๐Ÿ“‹ User ${this.userId}: Received session info:`, { userId: this.sessionInfo.userId, sessionId: this.sessionInfo.sessionId, connectionId: this.sessionInfo.connectionId }); // Check if LiveKit agent should be starting console.log(`๐Ÿš€ User ${this.userId}: LiveKit agent should be starting for room: mcp-chrome-user-${this.sessionInfo.userId}`); this.liveKitAgentStarted = true; resolve(); } else { console.log(`๐Ÿ“จ User ${this.userId}: Received message:`, message); } } catch (error) { console.error(`โŒ User ${this.userId}: Error parsing message:`, error); } }); this.ws.on('close', () => { console.log(`๐Ÿ”Œ User ${this.userId}: Chrome extension disconnected`); this.connected = false; }); this.ws.on('error', (error) => { console.error(`โŒ User ${this.userId}: Connection error:`, error); reject(error); }); // Timeout after 10 seconds setTimeout(() => { if (!this.sessionInfo) { reject(new Error(`User ${this.userId}: Timeout waiting for session info`)); } }, 10000); }); } async sendTestCommand() { if (!this.connected || !this.ws) { throw new Error(`User ${this.userId}: Not connected`); } const testCommand = { action: 'callTool', params: { name: 'chrome_navigate', arguments: { url: `https://example.com?user=${this.userId}` } }, id: `test_${this.userId}_${Date.now()}` }; console.log(`๐ŸŒ User ${this.userId}: Sending navigation command`); this.ws.send(JSON.stringify(testCommand)); } disconnect() { if (this.ws) { console.log(`๐Ÿ‘‹ User ${this.userId}: Disconnecting Chrome extension`); this.ws.close(); } } getStatus() { return { userId: this.userId, connected: this.connected, sessionInfo: this.sessionInfo, liveKitAgentStarted: this.liveKitAgentStarted, expectedRoom: this.sessionInfo ? `mcp-chrome-user-${this.sessionInfo.userId}` : null }; } } async function testMultiUserLiveKitIntegration() { console.log('๐Ÿš€ Testing Multi-User Chrome Extension to LiveKit Agent Integration\n'); console.log(`๐Ÿ“Š Creating ${NUM_USERS} simulated Chrome extension users...\n`); const users = []; try { // Create and connect multiple users for (let i = 1; i <= NUM_USERS; i++) { const user = new TestChromeUser(i); users.push(user); console.log(`\n--- Connecting User ${i} ---`); await user.connect(); // Wait a bit between connections to see the sequential startup await new Promise(resolve => setTimeout(resolve, 2000)); } console.log('\n๐ŸŽ‰ All Chrome extensions connected successfully!'); // Display session summary console.log('\n๐Ÿ“Š SESSION AND LIVEKIT AGENT SUMMARY:'); console.log('=' * 80); users.forEach(user => { const status = user.getStatus(); console.log(`๐Ÿ‘ค User ${status.userId}:`); console.log(` ๐Ÿ“‹ Session ID: ${status.sessionInfo?.sessionId || 'N/A'}`); console.log(` ๐Ÿ†” User ID: ${status.sessionInfo?.userId || 'N/A'}`); console.log(` ๐Ÿ  Expected LiveKit Room: ${status.expectedRoom || 'N/A'}`); console.log(` ๐Ÿš€ LiveKit Agent Started: ${status.liveKitAgentStarted ? 'โœ… YES' : 'โŒ NO'}`); console.log(''); }); // Test sending commands from each user console.log('\n--- Testing Commands from Each User ---'); for (const user of users) { await user.sendTestCommand(); await new Promise(resolve => setTimeout(resolve, 1000)); } // Wait for responses and LiveKit agent startup console.log('\nโณ Waiting for LiveKit agents to start and process commands...'); await new Promise(resolve => setTimeout(resolve, 10000)); // Test session isolation console.log('\n๐Ÿ” Session Isolation Test:'); const sessionIds = users.map(user => user.sessionInfo?.sessionId).filter(Boolean); const userIds = users.map(user => user.sessionInfo?.userId).filter(Boolean); const uniqueSessionIds = new Set(sessionIds); const uniqueUserIds = new Set(userIds); console.log(` Total users: ${users.length}`); console.log(` Unique session IDs: ${uniqueSessionIds.size}`); console.log(` Unique user IDs: ${uniqueUserIds.size}`); console.log(` Session isolation: ${uniqueSessionIds.size === users.length ? 'โœ… PASS' : 'โŒ FAIL'}`); console.log(` User ID isolation: ${uniqueUserIds.size === users.length ? 'โœ… PASS' : 'โŒ FAIL'}`); // Test LiveKit room naming console.log('\n๐Ÿ  LiveKit Room Naming Test:'); const expectedRooms = users.map(user => user.getStatus().expectedRoom).filter(Boolean); const uniqueRooms = new Set(expectedRooms); console.log(` Expected rooms: ${expectedRooms.length}`); console.log(` Unique rooms: ${uniqueRooms.size}`); console.log(` Room isolation: ${uniqueRooms.size === users.length ? 'โœ… PASS' : 'โŒ FAIL'}`); expectedRooms.forEach((room, index) => { console.log(` User ${index + 1} โ†’ Room: ${room}`); }); } catch (error) { console.error('โŒ Test failed:', error); } finally { // Clean up connections console.log('\n๐Ÿงน Cleaning up connections...'); users.forEach(user => user.disconnect()); setTimeout(() => { console.log('\nโœ… Multi-user LiveKit integration test completed'); console.log('\n๐Ÿ“ Expected Results:'); console.log(' - Each Chrome extension gets a unique session ID'); console.log(' - Each user gets a unique LiveKit room (mcp-chrome-user-{userId})'); console.log(' - LiveKit agents start automatically for each Chrome connection'); console.log(' - Commands are routed to the correct user\'s Chrome extension'); console.log(' - LiveKit agents stop when Chrome extensions disconnect'); process.exit(0); }, 2000); } } // Check if server is running console.log('๐Ÿ” Checking if remote server is running...'); const testWs = new WebSocket(SERVER_URL); testWs.on('open', () => { testWs.close(); console.log('โœ… Remote server is running, starting multi-user LiveKit test...\n'); testMultiUserLiveKitIntegration(); }); testWs.on('error', (error) => { console.error('โŒ Cannot connect to remote server. Please start the remote server first:'); console.error(' cd app/remote-server && npm start'); console.error('\nError:', error.message); process.exit(1); });