Major refactor: Multi-user Chrome MCP extension with remote server architecture
This commit is contained in:
230
app/remote-server/test-multi-user-livekit.js
Normal file
230
app/remote-server/test-multi-user-livekit.js
Normal file
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
* 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);
|
||||
});
|
Reference in New Issue
Block a user