sam-coder-cli 1.0.15 ā 1.0.16
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 +182 -69
- package/package.json +1 -1
|
@@ -235,59 +235,61 @@ class MultiplayerClient extends EventEmitter {
|
|
|
235
235
|
this.clients = [];
|
|
236
236
|
this.currentTask = null;
|
|
237
237
|
this.taskQueue = [];
|
|
238
|
+
this.pendingTasks = new Map();
|
|
239
|
+
this.taskResults = new Map();
|
|
238
240
|
this.rl = options.rl || readline.createInterface({
|
|
239
241
|
input: process.stdin,
|
|
240
242
|
output: process.stdout
|
|
241
243
|
});
|
|
244
|
+
|
|
245
|
+
// Bind methods
|
|
246
|
+
this.processTaskQueue = this.processTaskQueue.bind(this);
|
|
247
|
+
this.completeTask = this.completeTask.bind(this);
|
|
242
248
|
}
|
|
243
249
|
|
|
244
250
|
async connect() {
|
|
245
251
|
try {
|
|
246
|
-
// Ensure server is running
|
|
247
|
-
|
|
248
|
-
const serverPort = url.port || 8080;
|
|
249
|
-
this.serverUrl = await ensureServerRunning(serverPort);
|
|
252
|
+
// Ensure server is running
|
|
253
|
+
this.serverUrl = await ensureServerRunning(this.port);
|
|
250
254
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
this.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
this.send({
|
|
258
|
-
type: 'client_info',
|
|
259
|
-
clientInfo: {
|
|
260
|
-
name: this.name || `Agent-${Math.random().toString(36).substr(2, 4)}`,
|
|
261
|
-
role: this.role || 'Assistant',
|
|
262
|
-
model: this.model || 'default'
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
this.emit('connected');
|
|
266
|
-
resolve();
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
this.ws.on('message', (data) => {
|
|
270
|
-
try {
|
|
271
|
-
const message = JSON.parse(data);
|
|
272
|
-
this.handleMessage(message);
|
|
273
|
-
} catch (error) {
|
|
274
|
-
console.error('Error parsing message:', error);
|
|
275
|
-
}
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
this.ws.on('close', () => {
|
|
279
|
-
this.connected = false;
|
|
280
|
-
this.emit('disconnected');
|
|
281
|
-
});
|
|
255
|
+
this.ws = new WebSocket(this.serverUrl);
|
|
256
|
+
|
|
257
|
+
this.ws.on('open', () => {
|
|
258
|
+
this.connected = true;
|
|
259
|
+
this.emit('connected');
|
|
260
|
+
console.log(chalk.green('ā
Connected to multiplayer server'));
|
|
282
261
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
262
|
+
// Send client info immediately after connection
|
|
263
|
+
this.updateClientInfo({
|
|
264
|
+
name: this.name,
|
|
265
|
+
role: this.role,
|
|
266
|
+
model: this.model
|
|
286
267
|
});
|
|
287
268
|
});
|
|
269
|
+
|
|
270
|
+
this.ws.on('message', (data) => {
|
|
271
|
+
try {
|
|
272
|
+
const message = JSON.parse(data);
|
|
273
|
+
this.handleMessage(message);
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.error('Error parsing message:', error);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
this.ws.on('close', () => {
|
|
280
|
+
this.connected = false;
|
|
281
|
+
this.emit('disconnected');
|
|
282
|
+
console.log(chalk.yellow('\nš Disconnected from multiplayer server'));
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
this.ws.on('error', (error) => {
|
|
286
|
+
console.error('WebSocket error:', error);
|
|
287
|
+
this.emit('error', error);
|
|
288
|
+
});
|
|
289
|
+
|
|
288
290
|
} catch (error) {
|
|
289
|
-
console.error('Failed to
|
|
290
|
-
|
|
291
|
+
console.error('Failed to connect to server:', error);
|
|
292
|
+
this.emit('error', error);
|
|
291
293
|
}
|
|
292
294
|
}
|
|
293
295
|
|
|
@@ -398,13 +400,22 @@ class MultiplayerClient extends EventEmitter {
|
|
|
398
400
|
this.emit('work_updated', message);
|
|
399
401
|
}
|
|
400
402
|
|
|
401
|
-
handleTaskAssigned(task) {
|
|
402
|
-
console.log(`\n New
|
|
403
|
-
console.log(`Type: ${task.taskType} | Assigned by: ${this.getClientName(task.assignedBy)}\n`);
|
|
403
|
+
async handleTaskAssigned(task) {
|
|
404
|
+
console.log(chalk.magenta(`\nš New Task: ${task.prompt}`));
|
|
405
|
+
console.log(chalk.dim(`Type: ${task.taskType} | Assigned by: ${this.getClientName(task.assignedBy)}\n`));
|
|
404
406
|
|
|
405
|
-
//
|
|
406
|
-
this.
|
|
407
|
-
|
|
407
|
+
// Store task in pending tasks
|
|
408
|
+
this.pendingTasks.set(task.id, {
|
|
409
|
+
...task,
|
|
410
|
+
status: 'pending',
|
|
411
|
+
assignedAt: new Date().toISOString()
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// Add to task queue if it's assigned to this client or to all
|
|
415
|
+
if (!task.assignedTo || task.assignedTo === this.clientId) {
|
|
416
|
+
this.taskQueue.push(task);
|
|
417
|
+
this.processTaskQueue();
|
|
418
|
+
}
|
|
408
419
|
|
|
409
420
|
this.emit('task_assigned', task);
|
|
410
421
|
}
|
|
@@ -413,34 +424,57 @@ class MultiplayerClient extends EventEmitter {
|
|
|
413
424
|
if (this.currentTask || this.taskQueue.length === 0) return;
|
|
414
425
|
|
|
415
426
|
this.currentTask = this.taskQueue.shift();
|
|
427
|
+
const taskId = this.currentTask.id;
|
|
416
428
|
|
|
417
429
|
try {
|
|
418
|
-
//
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
const result = {
|
|
426
|
-
taskId: this.currentTask.id,
|
|
427
|
-
result: `Completed task: ${this.currentTask.prompt}`,
|
|
428
|
-
timestamp: new Date().toISOString()
|
|
429
|
-
};
|
|
430
|
+
// Update task status to in-progress
|
|
431
|
+
this.pendingTasks.set(taskId, {
|
|
432
|
+
...this.pendingTasks.get(taskId),
|
|
433
|
+
status: 'in_progress',
|
|
434
|
+
startedAt: new Date().toISOString()
|
|
435
|
+
});
|
|
430
436
|
|
|
431
|
-
//
|
|
437
|
+
// Notify others about task progress
|
|
432
438
|
this.send({
|
|
433
|
-
type: '
|
|
439
|
+
type: 'task_progress',
|
|
434
440
|
sessionId: this.sessionId,
|
|
435
|
-
taskId
|
|
436
|
-
|
|
437
|
-
|
|
441
|
+
taskId,
|
|
442
|
+
status: 'in_progress',
|
|
443
|
+
progress: 0,
|
|
444
|
+
timestamp: new Date().toISOString()
|
|
438
445
|
});
|
|
439
446
|
|
|
440
|
-
console.log(
|
|
447
|
+
console.log(chalk.blue(`\nš [${this.role}] Working on: ${this.currentTask.prompt}`));
|
|
448
|
+
|
|
449
|
+
// Simulate work with progress updates
|
|
450
|
+
const totalSteps = 5;
|
|
451
|
+
for (let i = 0; i < totalSteps; i++) {
|
|
452
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
453
|
+
const progress = Math.floor(((i + 1) / totalSteps) * 100);
|
|
454
|
+
|
|
455
|
+
// Update progress
|
|
456
|
+
this.send({
|
|
457
|
+
type: 'task_progress',
|
|
458
|
+
sessionId: this.sessionId,
|
|
459
|
+
taskId,
|
|
460
|
+
status: 'in_progress',
|
|
461
|
+
progress,
|
|
462
|
+
timestamp: new Date().toISOString()
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Complete the task
|
|
467
|
+
await this.completeTask(taskId);
|
|
441
468
|
|
|
442
469
|
} catch (error) {
|
|
443
470
|
console.error('Error processing task:', error);
|
|
471
|
+
this.send({
|
|
472
|
+
type: 'task_failed',
|
|
473
|
+
sessionId: this.sessionId,
|
|
474
|
+
taskId,
|
|
475
|
+
error: error.message,
|
|
476
|
+
timestamp: new Date().toISOString()
|
|
477
|
+
});
|
|
444
478
|
} finally {
|
|
445
479
|
this.currentTask = null;
|
|
446
480
|
// Process next task if available
|
|
@@ -449,6 +483,52 @@ class MultiplayerClient extends EventEmitter {
|
|
|
449
483
|
}
|
|
450
484
|
}
|
|
451
485
|
}
|
|
486
|
+
|
|
487
|
+
async completeTask(taskId) {
|
|
488
|
+
const task = this.pendingTasks.get(taskId);
|
|
489
|
+
if (!task) return null;
|
|
490
|
+
|
|
491
|
+
// Generate task result based on task type
|
|
492
|
+
let result;
|
|
493
|
+
switch (task.taskType) {
|
|
494
|
+
case 'research':
|
|
495
|
+
result = `Research completed on: ${task.prompt}\nSummary: This is a simulated research result.`;
|
|
496
|
+
break;
|
|
497
|
+
case 'code':
|
|
498
|
+
result = `Code implementation for: ${task.prompt}\n// Simulated code implementation\nfunction ${task.prompt.split(' ')[0].toLowerCase()}() {\n // TODO: Implement\n}`;
|
|
499
|
+
break;
|
|
500
|
+
case 'debug':
|
|
501
|
+
result = `Debugging analysis for: ${task.prompt}\n- Issue identified: Simulated issue\n- Solution: Simulated fix`;
|
|
502
|
+
break;
|
|
503
|
+
default:
|
|
504
|
+
result = `Completed: ${task.prompt}`;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Update task status
|
|
508
|
+
const completedTask = {
|
|
509
|
+
...task,
|
|
510
|
+
status: 'completed',
|
|
511
|
+
completedAt: new Date().toISOString(),
|
|
512
|
+
result
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
this.pendingTasks.set(taskId, completedTask);
|
|
516
|
+
this.taskResults.set(taskId, result);
|
|
517
|
+
|
|
518
|
+
// Notify server and other clients
|
|
519
|
+
this.send({
|
|
520
|
+
type: 'task_completed',
|
|
521
|
+
sessionId: this.sessionId,
|
|
522
|
+
taskId,
|
|
523
|
+
result,
|
|
524
|
+
timestamp: new Date().toISOString()
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
console.log(chalk.green(`\nā
[${this.role}] Completed: ${task.prompt}`));
|
|
528
|
+
this.emit('task_completed', completedTask);
|
|
529
|
+
|
|
530
|
+
return completedTask;
|
|
531
|
+
}
|
|
452
532
|
|
|
453
533
|
handleTaskCompleted(data) {
|
|
454
534
|
console.log(`\n Task completed by all agents!`);
|
|
@@ -462,19 +542,52 @@ class MultiplayerClient extends EventEmitter {
|
|
|
462
542
|
this.emit('task_completed', data);
|
|
463
543
|
}
|
|
464
544
|
|
|
465
|
-
updateWork(work) {
|
|
545
|
+
async updateWork(work) {
|
|
466
546
|
const workItem = {
|
|
547
|
+
id: uuidv4(),
|
|
467
548
|
...work,
|
|
468
549
|
clientId: this.clientId,
|
|
469
|
-
|
|
470
|
-
timestamp: new Date().toISOString()
|
|
550
|
+
clientName: this.name,
|
|
551
|
+
timestamp: new Date().toISOString(),
|
|
552
|
+
status: work.status || 'in_progress'
|
|
471
553
|
};
|
|
472
|
-
|
|
554
|
+
|
|
555
|
+
this.workHistory.push(workItem);
|
|
556
|
+
|
|
557
|
+
// Keep only the last 10 work items
|
|
558
|
+
if (this.workHistory.length > 10) {
|
|
559
|
+
this.workHistory = this.workHistory.slice(-10);
|
|
560
|
+
}
|
|
561
|
+
|
|
473
562
|
this.send({
|
|
474
563
|
type: 'work_update',
|
|
475
564
|
sessionId: this.sessionId,
|
|
476
|
-
|
|
565
|
+
...workItem
|
|
477
566
|
});
|
|
567
|
+
|
|
568
|
+
this.emit('work_updated', workItem);
|
|
569
|
+
return workItem;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
async updateClientInfo(updates) {
|
|
573
|
+
// Update local client info
|
|
574
|
+
Object.assign(this, updates);
|
|
575
|
+
|
|
576
|
+
// Notify server about the update
|
|
577
|
+
if (this.connected) {
|
|
578
|
+
this.send({
|
|
579
|
+
type: 'client_update',
|
|
580
|
+
sessionId: this.sessionId,
|
|
581
|
+
clientId: this.clientId,
|
|
582
|
+
updates: {
|
|
583
|
+
name: this.name,
|
|
584
|
+
role: this.role,
|
|
585
|
+
model: this.model,
|
|
586
|
+
updatedAt: new Date().toISOString()
|
|
587
|
+
},
|
|
588
|
+
timestamp: new Date().toISOString()
|
|
589
|
+
});
|
|
590
|
+
}
|
|
478
591
|
}
|
|
479
592
|
|
|
480
593
|
assignTask(task, assigneeClientId) {
|