sam-coder-cli 1.0.43 → 1.0.44

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.
@@ -1,276 +0,0 @@
1
- const AITeam = require('./ai-team');
2
- const readline = require('readline');
3
- const chalk = require('chalk');
4
- const ui = require('./ui');
5
-
6
- class MultiplayerMode {
7
- constructor(options = {}) {
8
- this.rl = options.rl || readline.createInterface({
9
- input: process.stdin,
10
- output: process.stdout
11
- });
12
-
13
- // Create AI Team instance
14
- this.aiTeam = new AITeam({
15
- name: options.agentName || this.generateAgentName(),
16
- role: options.role || 'DEVELOPER',
17
- model: options.model || 'deepseek/deepseek-chat-v3-0324:free',
18
- rl: this.rl,
19
- serverUrl: options.serverUrl
20
- });
21
-
22
- this.agentRole = options.role || 'DEVELOPER';
23
- this.isWorking = false;
24
- }
25
-
26
- generateAgentName() {
27
- const adjectives = ['Swift', 'Clever', 'Wise', 'Agile', 'Smart', 'Quick', 'Bright', 'Sharp'];
28
- const nouns = ['Coder', 'Thinker', 'Solver', 'Creator', 'Builder', 'Planner', 'Strategist'];
29
- const randomAdjective = adjectives[Math.floor(Math.random() * adjectives.length)];
30
- const randomNoun = nouns[Math.floor(Math.random() * nouns.length)];
31
- return `${randomAdjective}${randomNoun}${Math.floor(100 + Math.random() * 900)}`;
32
- }
33
-
34
- setupEventListeners() {
35
- // Event listeners are now handled by AICollaboration class
36
- }
37
-
38
- async start() {
39
- console.clear();
40
- ui.showHeader();
41
- console.log(chalk.blue.bold('=== AI Team Collaboration Mode ==='));
42
-
43
- try {
44
- // Get session ID to join or create a new one
45
- const sessionId = await this.askQuestion('\nEnter session ID to join (or press Enter to create a new session): ');
46
-
47
- await this.aiTeam.start(sessionId || undefined);
48
-
49
- // Keep the process alive
50
- this.rl.on('close', () => {
51
- console.log('\nDisconnecting from collaboration session...');
52
- process.exit(0);
53
- });
54
- } catch (error) {
55
- console.error(chalk.red(`\nError: ${error.message}`));
56
- console.error(error.stack);
57
- this.rl.close();
58
- process.exit(1);
59
- }
60
- }
61
-
62
- async askQuestion(question) {
63
- return new Promise((resolve) => {
64
- this.rl.question(question, (answer) => {
65
- resolve(answer.trim());
66
- });
67
- });
68
- }
69
-
70
- async joinSession(sessionId) {
71
- this.client.joinSession(sessionId);
72
- }
73
-
74
- async createSession() {
75
- console.log(chalk.yellow('Creating a new session...'));
76
- this.client.createSession();
77
- }
78
-
79
- setupCommandHandlers() {
80
- this.client.on('command', async (command) => {
81
- await this.handleCommand(command);
82
- });
83
- }
84
-
85
- async handleCommand(input) {
86
- const [command, ...args] = input.slice(1).split(' ');
87
-
88
- try {
89
- switch (command.toLowerCase()) {
90
- case 'name':
91
- if (args.length > 0) {
92
- const newName = args.join(' ');
93
- this.client.name = newName;
94
- await this.client.updateClientInfo({ name: newName });
95
- console.log(chalk.green(`✅ Name updated to: ${newName}`));
96
- } else {
97
- console.log(chalk.yellow(`Current name: ${this.client.name}`));
98
- }
99
- break;
100
-
101
- case 'role':
102
- if (args.length > 0) {
103
- const newRole = args.join(' ');
104
- this.client.role = newRole;
105
- await this.client.updateClientInfo({ role: newRole });
106
- console.log(chalk.green(`✅ Role updated to: ${newRole}`));
107
- } else {
108
- console.log(chalk.yellow(`Current role: ${this.client.role}`));
109
- }
110
- break;
111
-
112
- case 'model':
113
- if (args.length > 0) {
114
- this.client.model = args[0];
115
- await this.client.updateClientInfo({ model: this.client.model });
116
- console.log(chalk.green(`✅ Model updated to: ${this.client.model}`));
117
- } else {
118
- console.log(chalk.yellow(`Current model: ${this.client.model}`));
119
- }
120
- break;
121
-
122
- case 'work':
123
- if (args.length > 0) {
124
- const workDesc = args.join(' ');
125
- this.client.updateWork({
126
- description: workDesc,
127
- status: 'in_progress',
128
- timestamp: new Date().toISOString()
129
- });
130
- console.log(chalk.green(`✅ Work updated: ${workDesc}`));
131
- } else {
132
- console.log(chalk.yellow('Please provide a work description. Example: /work Fixing bugs'));
133
- }
134
- break;
135
-
136
- case 'collab':
137
- case 'collaborate':
138
- if (args.length > 0) {
139
- if (!this.client.isHost) {
140
- console.log(chalk.yellow('Only the session host can initiate collaboration'));
141
- break;
142
- }
143
- const taskType = args[0].toLowerCase();
144
- const prompt = args.slice(1).join(' ');
145
-
146
- if (!Object.values(MultiplayerClient.TASK_TYPES).includes(taskType)) {
147
- console.log(chalk.yellow(`Invalid task type. Available types: ${Object.values(MultiplayerClient.TASK_TYPES).join(', ')}`));
148
- break;
149
- }
150
-
151
- if (!prompt) {
152
- console.log(chalk.yellow('Please provide a task prompt. Example: /collab research How does quantum computing work?'));
153
- break;
154
- }
155
-
156
- console.log(chalk.blue(`\n🤝 Starting collaborative ${taskType} task: ${prompt}`));
157
- await this.client.collaborate(prompt, taskType);
158
-
159
- } else {
160
- console.log(chalk.yellow('Usage: /collab <type> <prompt>'));
161
- console.log(chalk.yellow('Types: ' + Object.values(MultiplayerClient.TASK_TYPES).join(', ')));
162
- }
163
- break;
164
-
165
- case 'task':
166
- if (args.length > 1) {
167
- const [target, ...taskArgs] = args;
168
- const taskDesc = taskArgs.join(' ');
169
-
170
- // Find the target client
171
- const targetClient = this.client.clients.find(c =>
172
- c.name.toLowerCase() === target.toLowerCase() ||
173
- c.clientId === target
174
- );
175
-
176
- if (!targetClient) {
177
- console.log(chalk.red(`❌ Could not find agent: ${target}`));
178
- break;
179
- }
180
-
181
- // In a real implementation, you would send this to the server
182
- // and the server would route it to the appropriate client
183
- console.log(chalk.blue(`\n📝 Task assigned to ${targetClient.name}: ${taskDesc}`));
184
-
185
- } else {
186
- console.log(chalk.yellow('Usage: /task <agent> <task description>'));
187
- console.log(chalk.yellow('Example: /task alice Please review the latest changes'));
188
- }
189
- break;
190
-
191
- case 'list':
192
- this.listAgents();
193
- break;
194
-
195
- case 'exit':
196
- console.log(chalk.yellow('\n👋 Disconnecting...'));
197
- process.exit(0);
198
- break;
199
-
200
- case 'help':
201
- this.showHelp();
202
- break;
203
-
204
- default:
205
- console.log(chalk.red(`❌ Unknown command: ${command}. Type /help for available commands.`));
206
- }
207
- } catch (error) {
208
- console.error(chalk.red(`\n❌ Error: ${error.message}`));
209
- }
210
-
211
- this.prompt();
212
- }
213
-
214
- showHelp() {
215
- console.log('\n=== 🆘 Available Commands ===');
216
- console.log('\n👤 Agent Management:');
217
- console.log(' /name [new_name] - Set or show your name');
218
- console.log(' /role [role] - Set or show your role');
219
- console.log(' /model [model_name] - Set or show your AI model');
220
-
221
- console.log('\n🤝 Collaboration:');
222
- console.log(' /work [description] - Update your work status');
223
- console.log(' /collab <type> <prompt> - Start a collaborative task');
224
- console.log(' Types: ' + Object.values(MultiplayerClient.TASK_TYPES).join(', '));
225
- console.log(' /task [agent] [task] - Assign a task to another agent');
226
-
227
- console.log('\n📋 Session:');
228
- console.log(' /list - List all agents in the session');
229
- console.log(' /exit - Leave the session');
230
- console.log(' /help - Show this help message');
231
-
232
- console.log('\n💡 Example:');
233
- console.log(' /collab research How does quantum computing work?');
234
- console.log(' /work Implementing user authentication');
235
- console.log(' /task bob Please review my latest changes');
236
- }
237
-
238
- listAgents() {
239
- console.log('\n=== 🧑‍💻 Agents in Session ===');
240
- if (this.client.clients.length === 0) {
241
- console.log('No other agents in the session');
242
- return;
243
- }
244
-
245
- this.client.clients.forEach(client => {
246
- const role = client.role ? ` (${client.role})` : '';
247
- const status = client.isHost ? '👑 ' : '👤 ';
248
- console.log(`${status}${client.name}${role} [${client.model}]`);
249
- if (client.work) {
250
- console.log(` ${client.work.status === 'completed' ? '✅' : '🔄'} ${client.work.description}`);
251
- }
252
- });
253
- }
254
-
255
- prompt() {
256
- if (this.isWorking) return;
257
-
258
- this.rl.question(chalk.blue('> '), async (input) => {
259
- if (!input.trim()) {
260
- this.prompt();
261
- return;
262
- }
263
-
264
- // Handle commands
265
- if (input.startsWith('/')) {
266
- await this.handleCommand(input);
267
- } else {
268
- // Regular chat message
269
- this.client.sendChatMessage(input);
270
- this.prompt();
271
- }
272
- });
273
- }
274
- }
275
-
276
- module.exports = MultiplayerMode;
@@ -1,372 +0,0 @@
1
- const WebSocket = require('ws');
2
- const http = require('http');
3
- const net = require('net');
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
- }
32
-
33
- class MultiplayerServer {
34
- constructor(port = 8080) {
35
- this.port = port;
36
- this.sessions = new Map();
37
- this.clients = new Map();
38
- this.tasks = new Map();
39
- this.httpServer = null;
40
- this.wss = null;
41
- }
42
-
43
- async start() {
44
- try {
45
- this.port = await findAvailablePort(this.port);
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
54
- this.setupEventHandlers();
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
- });
68
- } catch (error) {
69
- console.error(chalk.red('Failed to start multiplayer server:'), error.message);
70
- throw error;
71
- }
72
- }
73
-
74
- static async startAsChildProcess(port = 8080) {
75
- const { spawn } = require('child_process');
76
- const serverProcess = spawn('node', [__filename, '--port', port.toString()], {
77
- detached: true,
78
- stdio: 'inherit',
79
- windowsHide: true
80
- });
81
-
82
- serverProcess.on('error', (error) => {
83
- console.error('Failed to start server process:', error);
84
- });
85
-
86
- serverProcess.unref();
87
- console.log(`Multiplayer server starting on port ${port}...`);
88
- return serverProcess;
89
- }
90
-
91
- setupEventHandlers() {
92
- if (!this.wss) {
93
- throw new Error('WebSocket server not initialized');
94
- }
95
-
96
- this.wss.on('connection', (ws) => {
97
- let clientId = uuid.v4();
98
- let sessionId = null;
99
- let clientInfo = {};
100
-
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
- }
111
- });
112
-
113
- ws.on('close', () => {
114
- // Remove client from any session
115
- if (sessionId && this.sessions.has(sessionId)) {
116
- const session = this.sessions.get(sessionId);
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
- }
133
- }
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);
142
- });
143
- });
144
- }
145
-
146
- handleMessage(ws, message) {
147
- try {
148
- const data = typeof message === 'string' ? JSON.parse(message) : message;
149
- const client = this.clients.get(ws);
150
-
151
- switch (data.type) {
152
- case 'client_info':
153
- if (client) {
154
- Object.assign(client, data.clientInfo);
155
- this.broadcastToSession(client.sessionId, {
156
- type: 'client_updated',
157
- clientId: client.id,
158
- clientInfo: data.clientInfo
159
- }, ws);
160
- }
161
- break;
162
-
163
- case 'create_session':
164
- this.handleCreateSession(ws, data);
165
- break;
166
-
167
- case 'join_session':
168
- this.handleJoinSession(ws, data);
169
- break;
170
-
171
- case 'collaborate':
172
- if (client && client.sessionId) {
173
- const taskId = uuid.v4();
174
- this.tasks.set(taskId, {
175
- id: taskId,
176
- sessionId: client.sessionId,
177
- prompt: data.prompt,
178
- status: 'in_progress',
179
- createdBy: client.id,
180
- createdAt: new Date().toISOString(),
181
- results: []
182
- });
183
-
184
- this.broadcastToSession(client.sessionId, {
185
- type: 'task_assigned',
186
- taskId,
187
- prompt: data.prompt,
188
- assignedBy: client.id
189
- });
190
- }
191
- break;
192
-
193
- case 'task_result':
194
- if (client && client.sessionId && data.taskId) {
195
- const task = this.tasks.get(data.taskId);
196
- if (task) {
197
- task.results.push({
198
- clientId: client.id,
199
- result: data.result,
200
- timestamp: new Date().toISOString()
201
- });
202
-
203
- // Check if all clients have responded
204
- const session = this.sessions.get(client.sessionId);
205
- if (session && task.results.length >= Object.keys(session.clients).length) {
206
- task.status = 'completed';
207
- this.broadcastToSession(client.sessionId, {
208
- type: 'task_completed',
209
- taskId: task.id,
210
- results: task.results
211
- });
212
- }
213
- }
214
- }
215
- break;
216
-
217
- case 'chat':
218
- case 'work_update':
219
- case 'task_update':
220
- this.broadcastToSession(data.sessionId, data);
221
- break;
222
-
223
- default:
224
- console.log('Unknown message type:', data.type);
225
- }
226
- } catch (error) {
227
- console.error('Error handling message:', error);
228
- }
229
- }
230
-
231
- handleCreateSession(ws, data) {
232
- const sessionId = uuid.v4();
233
- const clientId = uuid.v4();
234
-
235
- // Store client info
236
- this.clients.set(ws, {
237
- id: clientId,
238
- sessionId,
239
- ws,
240
- isHost: true,
241
- name: data.name || `Agent-${Math.random().toString(36).substr(2, 4)}`,
242
- role: data.role || 'Assistant',
243
- model: data.model || 'default'
244
- });
245
-
246
- this.sessions.set(sessionId, {
247
- id: sessionId,
248
- clients: { [clientId]: true },
249
- workHistory: [],
250
- createdAt: new Date().toISOString(),
251
- hostId: clientId
252
- });
253
-
254
- // Send session created confirmation
255
- ws.send(JSON.stringify({
256
- type: 'session_created',
257
- sessionId,
258
- clientId,
259
- isHost: true
260
- }));
261
- }
262
-
263
- handleJoinSession(ws, data) {
264
- const { sessionId } = data;
265
- const clientId = data.clientId || uuid.v4();
266
-
267
- // If session doesn't exist, create it (this allows for reconnection)
268
- if (!this.sessions.has(sessionId)) {
269
- console.log(`Session ${sessionId} not found, creating new session`);
270
- this.sessions.set(sessionId, {
271
- id: sessionId,
272
- clients: {},
273
- createdAt: new Date().toISOString(),
274
- hostId: clientId, // First joiner becomes host if session didn't exist
275
- tasks: []
276
- });
277
- }
278
-
279
- const session = this.sessions.get(sessionId);
280
-
281
- // Check if session is full (max 4 agents)
282
- if (Object.keys(session.clients).length >= 4 && !session.clients[clientId]) {
283
- ws.send(JSON.stringify({
284
- type: 'error',
285
- message: 'Session is full (max 4 agents)'
286
- }));
287
- return;
288
- }
289
-
290
- // Store/update client info
291
- const existingClient = Array.from(this.clients.entries())
292
- .find(([_, c]) => c.id === clientId)?.[1];
293
-
294
- const clientInfo = {
295
- id: clientId,
296
- sessionId,
297
- ws,
298
- isHost: session.hostId === clientId,
299
- name: data.name || existingClient?.name || `Agent-${clientId.substr(0, 4)}`,
300
- role: data.role || existingClient?.role || 'Assistant',
301
- model: data.model || existingClient?.model || 'default',
302
- joinedAt: new Date().toISOString(),
303
- lastSeen: new Date().toISOString()
304
- };
305
-
306
- // Add client to session
307
- session.clients[clientId] = clientInfo;
308
- this.clients.set(ws, clientInfo);
309
-
310
- // Send session joined confirmation
311
- ws.send(JSON.stringify({
312
- type: 'session_joined',
313
- sessionId,
314
- clientId,
315
- clientInfo,
316
- isHost: clientInfo.isHost,
317
- sessionInfo: {
318
- id: session.id,
319
- createdAt: session.createdAt,
320
- clientCount: Object.keys(session.clients).length,
321
- hostId: session.hostId
322
- }
323
- }));
324
-
325
- // Notify other clients in the session
326
- this.broadcastToSession(sessionId, {
327
- type: 'agent_joined',
328
- clientId,
329
- clientInfo,
330
- timestamp: new Date().toISOString()
331
- }, clientId);
332
- }
333
-
334
- broadcastToSession(sessionId, message, excludeClientId = null) {
335
- if (!this.sessions.has(sessionId)) return;
336
-
337
- const session = this.sessions.get(sessionId);
338
- const messageStr = JSON.stringify(message);
339
-
340
- Object.entries(session.clients).forEach(([id, client]) => {
341
- if (id !== excludeClientId && client.ws && client.ws.readyState === WebSocket.OPEN) {
342
- client.ws.send(messageStr);
343
- }
344
- });
345
- }
346
-
347
- start() {
348
- return new Promise((resolve, reject) => {
349
- this.httpServer = http.createServer();
350
- this.wss = new WebSocket.Server({ server: this.httpServer });
351
- this.setupEventHandlers();
352
-
353
- this.httpServer.on('error', (error) => {
354
- console.error(chalk.red('HTTP server error:'), error);
355
- reject(error);
356
- });
357
-
358
- this.httpServer.listen(this.port, () => {
359
- console.log(chalk.green(`Multiplayer server started on port ${this.port}`));
360
- resolve(this.port);
361
- });
362
- });
363
- }
364
- }
365
-
366
- // Start server if run directly
367
- if (require.main === module) {
368
- const server = new MultiplayerServer();
369
- server.start();
370
- }
371
-
372
- module.exports = MultiplayerServer;