238 lines
7.6 KiB
JavaScript
238 lines
7.6 KiB
JavaScript
/**
|
|
* Complete Multi-User System Test
|
|
* Tests the full flow: Chrome Extension → Remote Server → LiveKit Agent → Voice Commands → Chrome Extension
|
|
*/
|
|
|
|
import WebSocket from 'ws';
|
|
|
|
const SERVER_URL = 'ws://localhost:3001/chrome';
|
|
const NUM_USERS = 2;
|
|
|
|
class TestChromeUser {
|
|
constructor(userId) {
|
|
this.userId = userId;
|
|
this.ws = null;
|
|
this.sessionInfo = null;
|
|
this.connected = false;
|
|
this.liveKitAgentStarted = false;
|
|
this.receivedMessages = [];
|
|
}
|
|
|
|
async connect() {
|
|
return new Promise((resolve, reject) => {
|
|
console.log(`\n🔌 [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;
|
|
|
|
// Generate unique user ID for this Chrome extension
|
|
const chromeUserId = `user_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
|
|
|
|
// Send connection info with user ID (simulating Chrome extension)
|
|
const connectionInfo = {
|
|
type: 'connection_info',
|
|
userId: chromeUserId, // Chrome extension provides its own user ID
|
|
userAgent: `TestChromeUser-${this.userId}`,
|
|
timestamp: Date.now(),
|
|
extensionId: `test-extension-${this.userId}`
|
|
};
|
|
|
|
console.log(`📤 [User ${this.userId}] Sending connection info with user ID: ${chromeUserId}`);
|
|
this.ws.send(JSON.stringify(connectionInfo));
|
|
});
|
|
|
|
this.ws.on('message', (data) => {
|
|
try {
|
|
const message = JSON.parse(data.toString());
|
|
this.receivedMessages.push(message);
|
|
|
|
console.log(`📨 [User ${this.userId}] Received message:`, message);
|
|
|
|
if (message.type === 'session_info') {
|
|
this.sessionInfo = message.sessionInfo;
|
|
console.log(`🎯 [User ${this.userId}] Session established:`, this.sessionInfo);
|
|
|
|
// Check if LiveKit agent should be started
|
|
setTimeout(() => {
|
|
this.checkLiveKitAgent();
|
|
}, 2000);
|
|
|
|
resolve();
|
|
}
|
|
|
|
// Handle tool calls from LiveKit agent
|
|
if (message.action === 'callTool') {
|
|
console.log(`🔧 [User ${this.userId}] Received tool call from LiveKit agent:`, message.params);
|
|
|
|
// Simulate Chrome extension response
|
|
const response = {
|
|
id: message.id,
|
|
success: true,
|
|
result: `Tool ${message.params.name} executed successfully for user ${this.userId}`,
|
|
timestamp: Date.now()
|
|
};
|
|
|
|
console.log(`📤 [User ${this.userId}] Sending tool response:`, response);
|
|
this.ws.send(JSON.stringify(response));
|
|
}
|
|
|
|
} 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}] WebSocket error:`, error);
|
|
reject(error);
|
|
});
|
|
|
|
// Timeout after 10 seconds
|
|
setTimeout(() => {
|
|
if (!this.sessionInfo) {
|
|
reject(new Error(`[User ${this.userId}] Timeout waiting for session info`));
|
|
}
|
|
}, 10000);
|
|
});
|
|
}
|
|
|
|
checkLiveKitAgent() {
|
|
if (this.sessionInfo) {
|
|
console.log(`🤖 [User ${this.userId}] LiveKit agent should be running for room: mcp-chrome-user-${this.sessionInfo.userId}`);
|
|
this.liveKitAgentStarted = true;
|
|
}
|
|
}
|
|
|
|
async sendTestVoiceCommand() {
|
|
if (!this.connected || !this.ws) {
|
|
throw new Error(`[User ${this.userId}] Not connected`);
|
|
}
|
|
|
|
// Simulate a voice command that would come from LiveKit agent
|
|
const voiceCommand = {
|
|
action: 'callTool',
|
|
params: {
|
|
name: 'chrome_navigate',
|
|
arguments: {
|
|
url: `https://example.com?user=${this.userId}&test=voice_command`,
|
|
userContext: this.sessionInfo?.userId
|
|
}
|
|
},
|
|
id: `voice_${this.userId}_${Date.now()}`,
|
|
source: 'livekit_agent'
|
|
};
|
|
|
|
console.log(`🎤 [User ${this.userId}] Simulating voice command:`, voiceCommand);
|
|
this.ws.send(JSON.stringify(voiceCommand));
|
|
}
|
|
|
|
getStatus() {
|
|
return {
|
|
userId: this.userId,
|
|
connected: this.connected,
|
|
sessionInfo: this.sessionInfo,
|
|
liveKitAgentStarted: this.liveKitAgentStarted,
|
|
messagesReceived: this.receivedMessages.length
|
|
};
|
|
}
|
|
|
|
disconnect() {
|
|
if (this.ws) {
|
|
console.log(`👋 [User ${this.userId}] Disconnecting Chrome extension`);
|
|
this.ws.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
async function testCompleteMultiUserSystem() {
|
|
console.log('🚀 Starting Complete Multi-User System Test...\n');
|
|
console.log('This test verifies:');
|
|
console.log('1. Chrome Extension User ID Generation');
|
|
console.log('2. Remote Server Session Management');
|
|
console.log('3. Automatic LiveKit Agent Spawning');
|
|
console.log('4. User ID Consistency Across Components');
|
|
console.log('5. Voice Command Routing\n');
|
|
|
|
const users = [];
|
|
|
|
try {
|
|
// Step 1: Connect multiple Chrome extension users
|
|
console.log('📋 STEP 1: Connecting Chrome Extension Users');
|
|
console.log('=' .repeat(50));
|
|
|
|
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();
|
|
console.log(`✅ User ${i} connected successfully`);
|
|
|
|
// Wait a bit between connections
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
}
|
|
|
|
// Step 2: Verify session isolation
|
|
console.log('\n📋 STEP 2: Verifying Session Isolation');
|
|
console.log('=' .repeat(50));
|
|
|
|
users.forEach(user => {
|
|
const status = user.getStatus();
|
|
console.log(`👤 User ${status.userId}:`);
|
|
console.log(` Session ID: ${status.sessionInfo?.sessionId}`);
|
|
console.log(` User ID: ${status.sessionInfo?.userId}`);
|
|
console.log(` LiveKit Agent: ${status.liveKitAgentStarted ? '✅ Started' : '❌ Not Started'}`);
|
|
});
|
|
|
|
// Step 3: Test voice command routing
|
|
console.log('\n📋 STEP 3: Testing Voice Command Routing');
|
|
console.log('=' .repeat(50));
|
|
|
|
for (const user of users) {
|
|
console.log(`\n🎤 Testing voice command for User ${user.userId}...`);
|
|
await user.sendTestVoiceCommand();
|
|
|
|
// Wait for response
|
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
}
|
|
|
|
// Step 4: Verify user isolation
|
|
console.log('\n📋 STEP 4: Verifying User Isolation');
|
|
console.log('=' .repeat(50));
|
|
|
|
users.forEach(user => {
|
|
const status = user.getStatus();
|
|
console.log(`👤 User ${status.userId}: Received ${status.messagesReceived} messages`);
|
|
});
|
|
|
|
console.log('\n✅ Multi-User System Test Completed Successfully!');
|
|
console.log('\n📊 SUMMARY:');
|
|
console.log(` Total Users: ${users.length}`);
|
|
console.log(` All Connected: ${users.every(u => u.connected)}`);
|
|
console.log(` All Have Sessions: ${users.every(u => u.sessionInfo)}`);
|
|
console.log(` All Have LiveKit Agents: ${users.every(u => u.liveKitAgentStarted)}`);
|
|
|
|
} catch (error) {
|
|
console.error('❌ Test failed:', error);
|
|
} finally {
|
|
// Cleanup
|
|
console.log('\n🧹 Cleaning up connections...');
|
|
users.forEach(user => user.disconnect());
|
|
|
|
setTimeout(() => {
|
|
console.log('✅ Test cleanup completed');
|
|
process.exit(0);
|
|
}, 2000);
|
|
}
|
|
}
|
|
|
|
// Run the test
|
|
testCompleteMultiUserSystem().catch(console.error);
|