sam-coder-cli 1.0.26 → 1.0.28
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.
- package/bin/multiplayer-client.js +29 -0
- package/bin/multiplayer-server.js +62 -16
- package/package.json +1 -1
|
@@ -695,9 +695,38 @@ class MultiplayerClient extends EventEmitter {
|
|
|
695
695
|
disconnect() {
|
|
696
696
|
if (this.ws) {
|
|
697
697
|
this.ws.close();
|
|
698
|
+
this.connected = false;
|
|
699
|
+
this.ws = null;
|
|
700
|
+
}
|
|
701
|
+
if (this.rl) {
|
|
702
|
+
this.rl.close();
|
|
698
703
|
}
|
|
699
704
|
}
|
|
700
705
|
|
|
706
|
+
sendChatMessage(message) {
|
|
707
|
+
if (!this.connected || !this.ws) {
|
|
708
|
+
console.error('Not connected to server');
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
try {
|
|
713
|
+
const chatMessage = {
|
|
714
|
+
type: 'chat_message',
|
|
715
|
+
sessionId: this.sessionId,
|
|
716
|
+
clientId: this.clientId,
|
|
717
|
+
sender: this.name,
|
|
718
|
+
message: message,
|
|
719
|
+
timestamp: new Date().toISOString()
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
this.ws.send(JSON.stringify(chatMessage));
|
|
723
|
+
return true;
|
|
724
|
+
} catch (error) {
|
|
725
|
+
console.error('Error sending chat message:', error);
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
701
730
|
getClientName(clientId) {
|
|
702
731
|
if (!clientId) return 'Unknown';
|
|
703
732
|
const client = this.clients.find(c => c.clientId === clientId || c.id === clientId);
|
|
@@ -36,16 +36,35 @@ class MultiplayerServer {
|
|
|
36
36
|
this.sessions = new Map();
|
|
37
37
|
this.clients = new Map();
|
|
38
38
|
this.tasks = new Map();
|
|
39
|
-
this.
|
|
39
|
+
this.httpServer = null;
|
|
40
|
+
this.wss = null;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
async start() {
|
|
43
44
|
try {
|
|
44
45
|
this.port = await findAvailablePort(this.port);
|
|
45
|
-
|
|
46
|
+
|
|
47
|
+
// Create HTTP server
|
|
48
|
+
this.httpServer = http.createServer();
|
|
49
|
+
|
|
50
|
+
// Create WebSocket server
|
|
51
|
+
this.wss = new WebSocket.Server({ server: this.httpServer });
|
|
52
|
+
|
|
53
|
+
// Setup event handlers
|
|
46
54
|
this.setupEventHandlers();
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
|
|
56
|
+
// Start listening
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
this.httpServer.on('error', (error) => {
|
|
59
|
+
console.error(chalk.red('HTTP server error:'), error);
|
|
60
|
+
reject(error);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
this.httpServer.listen(this.port, () => {
|
|
64
|
+
console.log(chalk.green(`Multiplayer server started on port ${this.port}`));
|
|
65
|
+
resolve(this.port);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
49
68
|
} catch (error) {
|
|
50
69
|
console.error(chalk.red('Failed to start multiplayer server:'), error.message);
|
|
51
70
|
throw error;
|
|
@@ -70,29 +89,56 @@ class MultiplayerServer {
|
|
|
70
89
|
}
|
|
71
90
|
|
|
72
91
|
setupEventHandlers() {
|
|
73
|
-
this.
|
|
92
|
+
if (!this.wss) {
|
|
93
|
+
throw new Error('WebSocket server not initialized');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this.wss.on('connection', (ws) => {
|
|
74
97
|
let clientId = uuid.v4();
|
|
75
98
|
let sessionId = null;
|
|
76
99
|
let clientInfo = {};
|
|
77
100
|
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
// Store client
|
|
102
|
+
this.clients.set(clientId, { ws, clientInfo });
|
|
103
|
+
|
|
104
|
+
ws.on('message', (data) => {
|
|
105
|
+
try {
|
|
106
|
+
const message = typeof data === 'string' ? JSON.parse(data) : data;
|
|
107
|
+
this.handleMessage(ws, clientId, message);
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error('Error processing message:', error);
|
|
110
|
+
}
|
|
80
111
|
});
|
|
81
112
|
|
|
82
113
|
ws.on('close', () => {
|
|
114
|
+
// Remove client from any session
|
|
83
115
|
if (sessionId && this.sessions.has(sessionId)) {
|
|
84
116
|
const session = this.sessions.get(sessionId);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
117
|
+
if (session && session.clients) {
|
|
118
|
+
delete session.clients[clientId];
|
|
119
|
+
|
|
120
|
+
// Notify other clients
|
|
121
|
+
this.broadcastToSession(sessionId, {
|
|
122
|
+
type: 'agent_left',
|
|
123
|
+
clientId,
|
|
124
|
+
clientInfo,
|
|
125
|
+
timestamp: new Date().toISOString()
|
|
126
|
+
}, clientId);
|
|
127
|
+
|
|
128
|
+
// Clean up empty sessions
|
|
129
|
+
if (Object.keys(session.clients).length === 0) {
|
|
130
|
+
this.sessions.delete(sessionId);
|
|
131
|
+
console.log(`Session ${sessionId} ended (no clients)`);
|
|
132
|
+
}
|
|
94
133
|
}
|
|
95
134
|
}
|
|
135
|
+
|
|
136
|
+
// Remove client from clients map
|
|
137
|
+
this.clients.delete(clientId);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
ws.on('error', (error) => {
|
|
141
|
+
console.error('WebSocket error:', error);
|
|
96
142
|
});
|
|
97
143
|
});
|
|
98
144
|
}
|