sam-coder-cli 1.0.24 → 1.0.26
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/agi-cli.js +11 -5
- package/bin/multiplayer-client.js +79 -26
- package/bin/multiplayer-server.js +59 -2
- package/package.json +1 -1
package/bin/agi-cli.js
CHANGED
|
@@ -752,11 +752,17 @@ async function start() {
|
|
|
752
752
|
|
|
753
753
|
// Check for server mode
|
|
754
754
|
if (process.argv.includes('--server')) {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
755
|
+
try {
|
|
756
|
+
const port = parseInt(process.argv[process.argv.indexOf('--port') + 1]) || 8080;
|
|
757
|
+
const MultiplayerServer = require('./multiplayer-server');
|
|
758
|
+
const server = new MultiplayerServer(port);
|
|
759
|
+
await server.start();
|
|
760
|
+
console.log(`Multiplayer server started on ws://localhost:${server.port}`);
|
|
761
|
+
return;
|
|
762
|
+
} catch (error) {
|
|
763
|
+
console.error('Failed to start multiplayer server:', error.message);
|
|
764
|
+
process.exit(1);
|
|
765
|
+
}
|
|
760
766
|
}
|
|
761
767
|
|
|
762
768
|
try {
|
|
@@ -704,38 +704,91 @@ class MultiplayerClient extends EventEmitter {
|
|
|
704
704
|
return client ? (client.name || client.clientInfo?.name || 'Unknown') : 'Unknown';
|
|
705
705
|
}
|
|
706
706
|
|
|
707
|
-
createSession() {
|
|
708
|
-
if (!this.
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
this.send({
|
|
714
|
-
type: 'create_session',
|
|
715
|
-
sessionId: this.sessionId,
|
|
716
|
-
clientInfo: {
|
|
717
|
-
name: this.name,
|
|
718
|
-
role: this.role,
|
|
719
|
-
model: this.model
|
|
707
|
+
async createSession() {
|
|
708
|
+
if (!this.connected) {
|
|
709
|
+
try {
|
|
710
|
+
await this.connect();
|
|
711
|
+
} catch (error) {
|
|
712
|
+
throw new Error(`Failed to connect to server: ${error.message}`);
|
|
720
713
|
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return new Promise((resolve, reject) => {
|
|
717
|
+
this.sessionId = uuidv4();
|
|
718
|
+
this.isHost = true;
|
|
719
|
+
|
|
720
|
+
const onSessionCreated = (data) => {
|
|
721
|
+
if (data.sessionId === this.sessionId) {
|
|
722
|
+
this.off('session_created', onSessionCreated);
|
|
723
|
+
this.off('error', onError);
|
|
724
|
+
resolve(this.sessionId);
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
const onError = (error) => {
|
|
729
|
+
this.off('session_created', onSessionCreated);
|
|
730
|
+
this.off('error', onError);
|
|
731
|
+
reject(error);
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
this.once('session_created', onSessionCreated);
|
|
735
|
+
this.once('error', onError);
|
|
736
|
+
|
|
737
|
+
this.send({
|
|
738
|
+
type: 'create_session',
|
|
739
|
+
sessionId: this.sessionId,
|
|
740
|
+
clientInfo: {
|
|
741
|
+
name: this.name,
|
|
742
|
+
role: this.role,
|
|
743
|
+
model: this.model
|
|
744
|
+
}
|
|
745
|
+
});
|
|
721
746
|
});
|
|
722
|
-
return this.sessionId;
|
|
723
747
|
}
|
|
724
748
|
|
|
725
|
-
joinSession(sessionId) {
|
|
726
|
-
if (!
|
|
727
|
-
throw new Error('
|
|
749
|
+
async joinSession(sessionId) {
|
|
750
|
+
if (!sessionId) {
|
|
751
|
+
throw new Error('Session ID is required');
|
|
728
752
|
}
|
|
729
|
-
|
|
730
|
-
this.
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
name: this.name,
|
|
736
|
-
role: this.role,
|
|
737
|
-
model: this.model
|
|
753
|
+
|
|
754
|
+
if (!this.connected) {
|
|
755
|
+
try {
|
|
756
|
+
await this.connect();
|
|
757
|
+
} catch (error) {
|
|
758
|
+
throw new Error(`Failed to connect to server: ${error.message}`);
|
|
738
759
|
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
return new Promise((resolve, reject) => {
|
|
763
|
+
this.sessionId = sessionId;
|
|
764
|
+
this.isHost = false;
|
|
765
|
+
|
|
766
|
+
const onSessionJoined = (data) => {
|
|
767
|
+
if (data.sessionId === this.sessionId) {
|
|
768
|
+
this.off('session_joined', onSessionJoined);
|
|
769
|
+
this.off('error', onError);
|
|
770
|
+
resolve();
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
const onError = (error) => {
|
|
775
|
+
this.off('session_joined', onSessionJoined);
|
|
776
|
+
this.off('error', onError);
|
|
777
|
+
reject(error);
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
this.once('session_joined', onSessionJoined);
|
|
781
|
+
this.once('error', onError);
|
|
782
|
+
|
|
783
|
+
this.send({
|
|
784
|
+
type: 'join_session',
|
|
785
|
+
sessionId: this.sessionId,
|
|
786
|
+
clientInfo: {
|
|
787
|
+
name: this.name,
|
|
788
|
+
role: this.role,
|
|
789
|
+
model: this.model
|
|
790
|
+
}
|
|
791
|
+
});
|
|
739
792
|
});
|
|
740
793
|
}
|
|
741
794
|
}
|
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
const WebSocket = require('ws');
|
|
2
2
|
const http = require('http');
|
|
3
|
+
const net = require('net');
|
|
3
4
|
const uuid = require('uuid');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
|
|
7
|
+
async function findAvailablePort(startPort = 8080, maxAttempts = 10) {
|
|
8
|
+
let port = startPort;
|
|
9
|
+
let attempts = 0;
|
|
10
|
+
|
|
11
|
+
while (attempts < maxAttempts) {
|
|
12
|
+
const inUse = await new Promise((resolve) => {
|
|
13
|
+
const server = net.createServer()
|
|
14
|
+
.once('error', () => resolve(true))
|
|
15
|
+
.once('listening', () => {
|
|
16
|
+
server.close();
|
|
17
|
+
resolve(false);
|
|
18
|
+
})
|
|
19
|
+
.listen(port);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (!inUse) {
|
|
23
|
+
return port;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
port++;
|
|
27
|
+
attempts++;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
throw new Error(`Could not find an available port after ${maxAttempts} attempts`);
|
|
31
|
+
}
|
|
4
32
|
|
|
5
33
|
class MultiplayerServer {
|
|
6
34
|
constructor(port = 8080) {
|
|
@@ -8,8 +36,37 @@ class MultiplayerServer {
|
|
|
8
36
|
this.sessions = new Map();
|
|
9
37
|
this.clients = new Map();
|
|
10
38
|
this.tasks = new Map();
|
|
11
|
-
this.server =
|
|
12
|
-
|
|
39
|
+
this.server = null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async start() {
|
|
43
|
+
try {
|
|
44
|
+
this.port = await findAvailablePort(this.port);
|
|
45
|
+
this.server = new WebSocket.Server({ port: this.port });
|
|
46
|
+
this.setupEventHandlers();
|
|
47
|
+
console.log(chalk.green(`Multiplayer server started on port ${this.port}`));
|
|
48
|
+
return this.port;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error(chalk.red('Failed to start multiplayer server:'), error.message);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static async startAsChildProcess(port = 8080) {
|
|
56
|
+
const { spawn } = require('child_process');
|
|
57
|
+
const serverProcess = spawn('node', [__filename, '--port', port.toString()], {
|
|
58
|
+
detached: true,
|
|
59
|
+
stdio: 'inherit',
|
|
60
|
+
windowsHide: true
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
serverProcess.on('error', (error) => {
|
|
64
|
+
console.error('Failed to start server process:', error);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
serverProcess.unref();
|
|
68
|
+
console.log(`Multiplayer server starting on port ${port}...`);
|
|
69
|
+
return serverProcess;
|
|
13
70
|
}
|
|
14
71
|
|
|
15
72
|
setupEventHandlers() {
|