sam-coder-cli 1.0.31 ā 1.0.33
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/ai-collaboration.js +175 -0
- package/bin/collaborate.js +48 -0
- package/bin/multiplayer-client.js +48 -10
- package/package.json +1 -1
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
const { MultiplayerClient } = require('./multiplayer-client');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const readline = require('readline');
|
|
4
|
+
const { v4: uuidv4 } = require('uuid');
|
|
5
|
+
|
|
6
|
+
class AICollaboration {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.client = new MultiplayerClient({
|
|
9
|
+
name: options.name || `Agent-${uuidv4().substr(0, 4)}`,
|
|
10
|
+
role: options.role || 'DEVELOPER',
|
|
11
|
+
model: options.model || 'default',
|
|
12
|
+
rl: options.rl
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
this.rl = options.rl || readline.createInterface({
|
|
16
|
+
input: process.stdin,
|
|
17
|
+
output: process.stdout
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
this.setupEventHandlers();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setupEventHandlers() {
|
|
24
|
+
this.client.on('connected', () => {
|
|
25
|
+
console.log(chalk.green('ā
Connected to multiplayer server'));
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
this.client.on('disconnected', () => {
|
|
29
|
+
console.log(chalk.yellow('Disconnected from multiplayer server'));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
this.client.on('error', (error) => {
|
|
33
|
+
console.error(chalk.red('Error:'), error.message);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
this.client.on('session_joined', (data) => {
|
|
37
|
+
console.log(chalk.green(`\nš Joined session ${data.sessionId} as ${this.client.name}`));
|
|
38
|
+
console.log(chalk.blue(`Role: ${this.client.role}`));
|
|
39
|
+
console.log(chalk.blue(`Host: ${data.isHost ? 'Yes' : 'No'}`));
|
|
40
|
+
|
|
41
|
+
if (data.isHost) {
|
|
42
|
+
console.log('\nAs the host, you can now enter a project prompt (e.g., "create a calculator"):');
|
|
43
|
+
this.promptForProject();
|
|
44
|
+
} else {
|
|
45
|
+
console.log('\nWaiting for host to start a project...');
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
this.client.on('task_assigned', (task) => {
|
|
50
|
+
console.log(chalk.yellow(`\nš Task assigned: ${task.description}`));
|
|
51
|
+
console.log('Working on task...');
|
|
52
|
+
|
|
53
|
+
// Simulate working on the task
|
|
54
|
+
setTimeout(() => {
|
|
55
|
+
const result = this.workOnTask(task);
|
|
56
|
+
console.log(chalk.green('ā
Task completed!'));
|
|
57
|
+
console.log('Result:', result);
|
|
58
|
+
|
|
59
|
+
this.client.completeTask(task.id, result);
|
|
60
|
+
}, 2000);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
this.client.on('task_completed', (data) => {
|
|
64
|
+
if (this.client.isHost) {
|
|
65
|
+
console.log(chalk.green(`\nšÆ Task ${data.taskId} completed by all agents!`));
|
|
66
|
+
console.log('Results:', JSON.stringify(data.results, null, 2));
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
this.client.on('chat_message', (message) => {
|
|
71
|
+
if (message.clientId !== this.client.clientId) {
|
|
72
|
+
console.log(`\nš¬ ${message.clientName || 'Unknown'}: ${message.text}`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async start(sessionId = null) {
|
|
78
|
+
try {
|
|
79
|
+
await this.client.connect();
|
|
80
|
+
|
|
81
|
+
if (sessionId) {
|
|
82
|
+
console.log(`Joining session ${sessionId}...`);
|
|
83
|
+
await this.client.joinSession(sessionId);
|
|
84
|
+
} else {
|
|
85
|
+
console.log('Creating new session...');
|
|
86
|
+
const newSessionId = await this.client.createSession();
|
|
87
|
+
console.log(`Created new session: ${newSessionId}`);
|
|
88
|
+
console.log('Share this ID with others to collaborate!');
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error(chalk.red('Failed to start AI collaboration:'), error.message);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
promptForProject() {
|
|
97
|
+
this.rl.question('\nš¹ Enter project prompt: ', async (prompt) => {
|
|
98
|
+
if (!prompt.trim()) {
|
|
99
|
+
console.log(chalk.yellow('Please enter a valid prompt'));
|
|
100
|
+
return this.promptForProject();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log(chalk.blue(`\nš¤ AI Team is working on: ${prompt}`));
|
|
104
|
+
|
|
105
|
+
// Divide tasks based on the prompt
|
|
106
|
+
const tasks = this.divideTasks(prompt);
|
|
107
|
+
|
|
108
|
+
// Assign tasks to agents
|
|
109
|
+
for (const task of tasks) {
|
|
110
|
+
this.client.assignTask(task);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
divideTasks(prompt) {
|
|
116
|
+
// Simple task division based on project type
|
|
117
|
+
const tasks = [];
|
|
118
|
+
|
|
119
|
+
if (prompt.toLowerCase().includes('calculator')) {
|
|
120
|
+
tasks.push(
|
|
121
|
+
{ id: 'task-1', type: 'ui', description: 'Design calculator UI', assignee: 'DEVELOPER' },
|
|
122
|
+
{ id: 'task-2', type: 'logic', description: 'Implement basic arithmetic operations', assignee: 'DEVELOPER' },
|
|
123
|
+
{ id: 'task-3', type: 'features', description: 'Add advanced functions (sqrt, power, etc.)', assignee: 'DEVELOPER' },
|
|
124
|
+
{ id: 'task-4', type: 'testing', description: 'Test calculator functionality', assignee: 'REVIEWER' }
|
|
125
|
+
);
|
|
126
|
+
} else if (prompt.toLowerCase().includes('todo')) {
|
|
127
|
+
tasks.push(
|
|
128
|
+
{ id: 'task-1', type: 'ui', description: 'Design todo list UI', assignee: 'DEVELOPER' },
|
|
129
|
+
{ id: 'task-2', type: 'data', description: 'Implement todo item storage', assignee: 'DEVELOPER' },
|
|
130
|
+
{ id: 'task-3', type: 'features', description: 'Add CRUD operations', assignee: 'DEVELOPER' },
|
|
131
|
+
{ id: 'task-4', type: 'features', description: 'Add filtering and sorting', assignee: 'DEVELOPER' },
|
|
132
|
+
{ id: 'task-5', type: 'testing', description: 'Test todo functionality', assignee: 'REVIEWER' }
|
|
133
|
+
);
|
|
134
|
+
} else {
|
|
135
|
+
// Default task division for unknown project types
|
|
136
|
+
tasks.push(
|
|
137
|
+
{ id: 'task-1', type: 'planning', description: 'Plan project structure', assignee: 'LEAD' },
|
|
138
|
+
{ id: 'task-2', type: 'research', description: 'Research required technologies', assignee: 'RESEARCHER' },
|
|
139
|
+
{ id: 'task-3', type: 'development', description: 'Implement core features', assignee: 'DEVELOPER' },
|
|
140
|
+
{ id: 'task-4', type: 'testing', description: 'Test the implementation', assignee: 'REVIEWER' }
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return tasks;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
workOnTask(task) {
|
|
148
|
+
// Simulate work based on task type
|
|
149
|
+
switch (task.type) {
|
|
150
|
+
case 'ui':
|
|
151
|
+
return 'UI implementation completed with responsive design';
|
|
152
|
+
case 'logic':
|
|
153
|
+
return 'Core logic implemented and tested';
|
|
154
|
+
case 'features':
|
|
155
|
+
return 'Additional features implemented successfully';
|
|
156
|
+
case 'testing':
|
|
157
|
+
return 'All tests passed successfully';
|
|
158
|
+
case 'planning':
|
|
159
|
+
return 'Project plan created with milestones';
|
|
160
|
+
case 'research':
|
|
161
|
+
return 'Research completed with technology recommendations';
|
|
162
|
+
default:
|
|
163
|
+
return 'Task completed successfully';
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
sendChatMessage(message) {
|
|
168
|
+
if (message && typeof message === 'string') {
|
|
169
|
+
this.client.sendChatMessage(message);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Export the AICollaboration class
|
|
175
|
+
module.exports = AICollaboration;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const AICollaboration = require('./ai-collaboration');
|
|
4
|
+
const readline = require('readline');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
|
|
7
|
+
// Create readline interface
|
|
8
|
+
const rl = readline.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stdout
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// Parse command line arguments
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
const sessionId = args[0];
|
|
16
|
+
const role = args[1]?.toUpperCase() || 'DEVELOPER';
|
|
17
|
+
|
|
18
|
+
console.log(chalk.cyan('\nš¤ AI Team Collaboration š¤'));
|
|
19
|
+
console.log(chalk.cyan('==========================\n'));
|
|
20
|
+
|
|
21
|
+
// Get user's name
|
|
22
|
+
rl.question('Enter your name (or press Enter for a random one): ', (name) => {
|
|
23
|
+
// Create AI collaboration instance
|
|
24
|
+
const aiCollab = new AICollaboration({
|
|
25
|
+
name: name.trim() || undefined,
|
|
26
|
+
role: role,
|
|
27
|
+
rl: rl
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Handle Ctrl+C to exit gracefully
|
|
31
|
+
process.on('SIGINT', () => {
|
|
32
|
+
console.log('\nš Disconnecting...');
|
|
33
|
+
process.exit(0);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Start the collaboration
|
|
37
|
+
aiCollab.start(sessionId).catch(error => {
|
|
38
|
+
console.error(chalk.red('Error:'), error.message);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Listen for chat messages
|
|
43
|
+
rl.on('line', (input) => {
|
|
44
|
+
if (input.trim()) {
|
|
45
|
+
aiCollab.sendChatMessage(input.trim());
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -733,23 +733,25 @@ class MultiplayerClient extends EventEmitter {
|
|
|
733
733
|
return client ? (client.name || client.clientInfo?.name || 'Unknown') : 'Unknown';
|
|
734
734
|
}
|
|
735
735
|
|
|
736
|
-
async createSession() {
|
|
736
|
+
async createSession(sessionId = null) {
|
|
737
737
|
if (!this.connected) {
|
|
738
|
-
|
|
739
|
-
await this.connect();
|
|
740
|
-
} catch (error) {
|
|
741
|
-
throw new Error(`Failed to connect to server: ${error.message}`);
|
|
742
|
-
}
|
|
738
|
+
await this.connect();
|
|
743
739
|
}
|
|
744
740
|
|
|
741
|
+
this.sessionId = sessionId || uuidv4();
|
|
742
|
+
this.isHost = true;
|
|
743
|
+
|
|
745
744
|
return new Promise((resolve, reject) => {
|
|
746
|
-
this.
|
|
747
|
-
|
|
745
|
+
if (!this.ws) {
|
|
746
|
+
reject(new Error('Not connected to server'));
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
748
749
|
|
|
749
750
|
const onSessionCreated = (data) => {
|
|
750
751
|
if (data.sessionId === this.sessionId) {
|
|
751
752
|
this.off('session_created', onSessionCreated);
|
|
752
753
|
this.off('error', onError);
|
|
754
|
+
console.log(`ā
Session ${this.sessionId} created successfully`);
|
|
753
755
|
resolve(this.sessionId);
|
|
754
756
|
}
|
|
755
757
|
};
|
|
@@ -757,12 +759,14 @@ class MultiplayerClient extends EventEmitter {
|
|
|
757
759
|
const onError = (error) => {
|
|
758
760
|
this.off('session_created', onSessionCreated);
|
|
759
761
|
this.off('error', onError);
|
|
762
|
+
console.error('Error creating session:', error.message);
|
|
760
763
|
reject(error);
|
|
761
764
|
};
|
|
762
765
|
|
|
763
766
|
this.once('session_created', onSessionCreated);
|
|
764
767
|
this.once('error', onError);
|
|
765
768
|
|
|
769
|
+
console.log(`Creating new session ${this.sessionId}...`);
|
|
766
770
|
this.send({
|
|
767
771
|
type: 'create_session',
|
|
768
772
|
sessionId: this.sessionId,
|
|
@@ -775,7 +779,7 @@ class MultiplayerClient extends EventEmitter {
|
|
|
775
779
|
});
|
|
776
780
|
}
|
|
777
781
|
|
|
778
|
-
async joinSession(sessionId) {
|
|
782
|
+
async joinSession(sessionId, createIfNotExists = true) {
|
|
779
783
|
if (!sessionId) {
|
|
780
784
|
throw new Error('Session ID is required');
|
|
781
785
|
}
|
|
@@ -791,9 +795,10 @@ class MultiplayerClient extends EventEmitter {
|
|
|
791
795
|
|
|
792
796
|
const timeout = setTimeout(() => {
|
|
793
797
|
this.off('session_joined', onSessionJoined);
|
|
798
|
+
this.off('session_created', onSessionCreated);
|
|
794
799
|
this.off('error', onError);
|
|
795
800
|
reject(new Error('Session join timed out'));
|
|
796
|
-
},
|
|
801
|
+
}, 15000); // Increased timeout to 15 seconds
|
|
797
802
|
|
|
798
803
|
const onSessionJoined = (data) => {
|
|
799
804
|
if (data.sessionId === sessionId) {
|
|
@@ -802,21 +807,54 @@ class MultiplayerClient extends EventEmitter {
|
|
|
802
807
|
this.isHost = data.isHost || false;
|
|
803
808
|
this.emit('session_joined', data);
|
|
804
809
|
this.off('session_joined', onSessionJoined);
|
|
810
|
+
this.off('session_created', onSessionCreated);
|
|
805
811
|
this.off('error', onError);
|
|
812
|
+
console.log(`ā
Successfully joined session ${sessionId}`);
|
|
806
813
|
resolve(data);
|
|
807
814
|
}
|
|
808
815
|
};
|
|
809
816
|
|
|
817
|
+
const onSessionCreated = (data) => {
|
|
818
|
+
if (data.sessionId === sessionId) {
|
|
819
|
+
clearTimeout(timeout);
|
|
820
|
+
this.sessionId = sessionId;
|
|
821
|
+
this.isHost = true;
|
|
822
|
+
this.emit('session_joined', { ...data, isHost: true });
|
|
823
|
+
this.off('session_joined', onSessionJoined);
|
|
824
|
+
this.off('session_created', onSessionCreated);
|
|
825
|
+
this.off('error', onError);
|
|
826
|
+
console.log(`ā
Created and joined new session ${sessionId}`);
|
|
827
|
+
resolve({ ...data, isHost: true });
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
|
|
810
831
|
const onError = (error) => {
|
|
832
|
+
if (error.message === 'Session not found' && createIfNotExists) {
|
|
833
|
+
// If session doesn't exist and we're allowed to create it
|
|
834
|
+
this.off('session_joined', onSessionJoined);
|
|
835
|
+
this.off('error', onError);
|
|
836
|
+
console.log(`Session ${sessionId} not found, creating new session...`);
|
|
837
|
+
this.createSession(sessionId)
|
|
838
|
+
.then(() => {
|
|
839
|
+
this.once('session_created', onSessionCreated);
|
|
840
|
+
this.once('error', onError);
|
|
841
|
+
})
|
|
842
|
+
.catch(reject);
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
|
|
811
846
|
clearTimeout(timeout);
|
|
812
847
|
this.off('session_joined', onSessionJoined);
|
|
848
|
+
this.off('session_created', onSessionCreated);
|
|
813
849
|
this.off('error', onError);
|
|
850
|
+
console.error('Error joining session:', error.message);
|
|
814
851
|
reject(error);
|
|
815
852
|
};
|
|
816
853
|
|
|
817
854
|
this.on('session_joined', onSessionJoined);
|
|
818
855
|
this.on('error', onError);
|
|
819
856
|
|
|
857
|
+
console.log(`Attempting to join session ${sessionId}...`);
|
|
820
858
|
this.send({
|
|
821
859
|
type: 'join_session',
|
|
822
860
|
sessionId: sessionId,
|