sam-coder-cli 1.0.32 → 1.0.34

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.
@@ -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;
package/bin/ai-team.js ADDED
@@ -0,0 +1,179 @@
1
+ const { callOpenRouter } = require('./agi-cli');
2
+ const { MultiplayerClient } = require('./multiplayer-client');
3
+ const readline = require('readline');
4
+ const chalk = require('chalk');
5
+ const { v4: uuidv4 } = require('uuid');
6
+
7
+ // System prompt for AI team collaboration
8
+ const TEAM_COLLABORATION_PROMPT = `You are an AI team facilitator that helps coordinate multiple AI agents working together on a project.
9
+
10
+ Your responsibilities include:
11
+ 1. Understanding the project requirements from the host
12
+ 2. Breaking down the project into clear, actionable tasks
13
+ 3. Assigning tasks to appropriate team members based on their roles
14
+ 4. Monitoring progress and coordinating between team members
15
+
16
+ When the host provides a project idea (e.g., "create a calculator"), you should:
17
+ 1. Analyze the requirements
18
+ 2. Break it down into logical components
19
+ 3. Create a task list with clear assignments
20
+ 4. Provide a summary of the plan
21
+
22
+ Respond in markdown format with clear sections for each part of your response.`;
23
+
24
+ class AITeam {
25
+ constructor(options = {}) {
26
+ this.client = new MultiplayerClient({
27
+ name: options.name || `Agent-${uuidv4().substr(0, 4)}`,
28
+ role: options.role || 'DEVELOPER',
29
+ model: options.model || 'deepseek/deepseek-chat-v3-0324:free',
30
+ rl: options.rl
31
+ });
32
+
33
+ this.rl = options.rl || readline.createInterface({
34
+ input: process.stdin,
35
+ output: process.stdout
36
+ });
37
+
38
+ this.conversation = [
39
+ { role: 'system', content: TEAM_COLLABORATION_PROMPT }
40
+ ];
41
+
42
+ this.setupEventHandlers();
43
+ }
44
+
45
+ setupEventHandlers() {
46
+ this.client.on('connected', () => {
47
+ console.log(chalk.green('āœ… Connected to multiplayer server'));
48
+ });
49
+
50
+ this.client.on('disconnected', () => {
51
+ console.log(chalk.yellow('Disconnected from multiplayer server'));
52
+ });
53
+
54
+ this.client.on('error', (error) => {
55
+ console.error(chalk.red('Error:'), error.message);
56
+ });
57
+
58
+ this.client.on('session_joined', async (data) => {
59
+ console.log(chalk.green(`\nšŸŽ‰ Joined session ${data.sessionId} as ${this.client.name}`));
60
+ console.log(chalk.blue(`Role: ${this.client.role}`));
61
+
62
+ if (data.isHost) {
63
+ console.log('\nAs the host, you can now enter a project prompt (e.g., "create a calculator"):');
64
+ await this.promptForProject();
65
+ } else {
66
+ console.log('\nWaiting for host to start a project...');
67
+ }
68
+ });
69
+
70
+ this.client.on('chat_message', async (message) => {
71
+ if (message.clientId !== this.client.clientId) {
72
+ console.log(`\nšŸ’¬ ${message.clientName || 'Unknown'}: ${message.text}`);
73
+
74
+ // If we receive a task assignment, process it
75
+ if (message.task) {
76
+ await this.processTask(message.task);
77
+ }
78
+ }
79
+ });
80
+ }
81
+
82
+ async start(sessionId = null) {
83
+ if (sessionId) {
84
+ console.log(`Joining session ${sessionId}...`);
85
+ await this.client.joinSession(sessionId);
86
+ } else {
87
+ console.log('Creating new session...');
88
+ const newSessionId = await this.client.createSession();
89
+ console.log(`Created new session: ${newSessionId}`);
90
+ console.log('Share this ID with others to collaborate!');
91
+ }
92
+
93
+ // Start chat input loop
94
+ this.rl.on('line', async (input) => {
95
+ if (input.trim()) {
96
+ if (this.client.isHost) {
97
+ await this.handleHostInput(input.trim());
98
+ } else {
99
+ await this.handleTeamMemberInput(input.trim());
100
+ }
101
+ }
102
+ });
103
+ }
104
+
105
+ async handleHostInput(input) {
106
+ // Add user message to conversation
107
+ this.conversation.push({ role: 'user', content: input });
108
+
109
+ // Get AI response
110
+ const response = await callOpenRouter(this.conversation, this.client.model);
111
+ const aiMessage = response.choices[0].message;
112
+
113
+ // Add AI response to conversation
114
+ this.conversation.push(aiMessage);
115
+
116
+ // Display response
117
+ console.log(`\nšŸ¤– ${aiMessage.content}\n`);
118
+
119
+ // If AI suggests tasks, assign them to team members
120
+ if (aiMessage.tool_calls) {
121
+ await this.handleToolCalls(aiMessage.tool_calls);
122
+ }
123
+
124
+ // Show prompt for next input
125
+ this.showPrompt();
126
+ }
127
+
128
+ async handleTeamMemberInput(input) {
129
+ // For team members, just send chat messages for now
130
+ this.client.sendChatMessage(input);
131
+ }
132
+
133
+ async handleToolCalls(toolCalls) {
134
+ for (const toolCall of toolCalls) {
135
+ if (toolCall.function.name === 'assign_task') {
136
+ const args = JSON.parse(toolCall.function.arguments);
137
+ await this.assignTask(args.role, args.task);
138
+ }
139
+ }
140
+ }
141
+
142
+ async assignTask(role, task) {
143
+ console.log(chalk.yellow(`\nšŸ“‹ Task for ${role}: ${task}`));
144
+
145
+ // In a real implementation, this would find the appropriate team member
146
+ // and assign them the task. For now, we'll just log it.
147
+ this.client.sendChatMessage(`Task assigned to ${role}: ${task}`, {
148
+ task: { role, description: task }
149
+ });
150
+ }
151
+
152
+ async processTask(task) {
153
+ console.log(chalk.blue(`\nšŸ“Œ Task received: ${task.description}`));
154
+
155
+ // Process the task using the AGI-CLI's tool calling system
156
+ const response = await callOpenRouter([
157
+ { role: 'system', content: `You are an AI assistant working on a task: ${task.description}` },
158
+ { role: 'user', content: 'Please complete this task step by step.' }
159
+ ], this.client.model, true);
160
+
161
+ const result = response.choices[0].message.content;
162
+ console.log(chalk.green('āœ… Task completed!'));
163
+ console.log(result);
164
+
165
+ // Notify the team of task completion
166
+ this.client.sendChatMessage(`Completed task: ${task.description}`);
167
+ }
168
+
169
+ showPrompt() {
170
+ const prefix = this.client.isHost ? 'šŸ‘‘ Host' : 'šŸ‘¤ You';
171
+ process.stdout.write(`\n${prefix} > `);
172
+ }
173
+
174
+ async promptForProject() {
175
+ this.showPrompt();
176
+ }
177
+ }
178
+
179
+ module.exports = AITeam;
@@ -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
- try {
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.sessionId = uuidv4();
747
- this.isHost = true;
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,
@@ -1,7 +1,6 @@
1
- const MultiplayerClient = require('./multiplayer-client');
1
+ const AITeam = require('./ai-team');
2
2
  const readline = require('readline');
3
3
  const chalk = require('chalk');
4
- const { v4: uuidv4 } = require('uuid');
5
4
  const ui = require('./ui');
6
5
 
7
6
  class MultiplayerMode {
@@ -11,15 +10,16 @@ class MultiplayerMode {
11
10
  output: process.stdout
12
11
  });
13
12
 
14
- this.client = new MultiplayerClient({
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',
15
18
  rl: this.rl,
16
- agentName: options.agentName || this.generateAgentName(),
17
- model: options.model || 'default',
18
19
  serverUrl: options.serverUrl
19
20
  });
20
21
 
21
- this.setupEventListeners();
22
- this.agentRole = '';
22
+ this.agentRole = options.role || 'DEVELOPER';
23
23
  this.isWorking = false;
24
24
  }
25
25
 
@@ -32,89 +32,31 @@ class MultiplayerMode {
32
32
  }
33
33
 
34
34
  setupEventListeners() {
35
- this.client.on('connected', () => {
36
- console.log(chalk.green('Connected to multiplayer server'));
37
- });
38
-
39
- this.client.on('disconnected', () => {
40
- console.log(chalk.yellow('Disconnected from multiplayer server'));
41
- });
42
-
43
- this.client.on('session_joined', (data) => {
44
- ui.showHeader();
45
- console.log(chalk.green(`\nJoined session: ${data.sessionId}`));
46
- console.log(chalk.blue(`You are: ${this.client.agentName}`));
47
- console.log(chalk.blue(`Model: ${this.client.model}`));
48
- console.log(chalk.blue(`Clients in session: ${Array.from(this.client.clients.values()).map(c => c.name).join(', ')}`));
49
-
50
- if (this.client.isHost) {
51
- console.log(chalk.yellow('\nYou are the host. Type /help for available commands.'));
52
- }
53
-
54
- this.prompt();
55
- });
56
-
57
- this.client.on('agent_joined', (data) => {
58
- console.log(chalk.blue(`\n${data.clientInfo.name} joined the session`));
59
- this.prompt();
60
- });
61
-
62
- this.client.on('agent_left', (data) => {
63
- const client = this.client.clients.get(data.clientId);
64
- if (client) {
65
- console.log(chalk.yellow(`\n${client.name} left the session`));
66
- this.prompt();
67
- }
68
- });
69
-
70
- this.client.on('chat', (message) => {
71
- // Chat messages are already handled by the client
72
- this.prompt();
73
- });
74
-
75
- this.client.on('work_updated', (data) => {
76
- this.prompt();
77
- });
78
-
79
- this.client.on('task_assigned', (task) => {
80
- console.log(chalk.magenta(`\n[New Task] ${task.description}`));
81
- this.prompt();
82
- });
83
-
84
- this.client.on('error', (error) => {
85
- console.error(chalk.red(`\nError: ${error.message}`));
86
- this.prompt();
87
- });
35
+ // Event listeners are now handled by AICollaboration class
88
36
  }
89
37
 
90
38
  async start() {
91
39
  console.clear();
92
40
  ui.showHeader();
93
- console.log(chalk.blue.bold('=== Multiplayer Mode ==='));
94
-
95
- // Set agent name
96
- this.client.name = await this.askQuestion('Enter your name (or press Enter for a random one): ') ||
97
- `Agent-${Math.random().toString(36).substr(2, 4)}`;
98
-
99
- // Set agent role
100
- console.log('\nAvailable roles:');
101
- Object.entries(MultiplayerClient.AGENT_ROLES).forEach(([key, value]) => {
102
- console.log(`- ${key}: ${value}`);
103
- });
104
- this.client.role = await this.askQuestion('\nChoose your role (or press Enter for Developer): ') ||
105
- MultiplayerClient.AGENT_ROLES.DEVELOPER;
106
-
107
- // Get session ID from user
108
- const sessionId = await this.askQuestion('\nEnter session ID to join or press Enter to create a new session: ');
41
+ console.log(chalk.blue.bold('=== AI Team Collaboration Mode ==='));
109
42
 
110
- if (sessionId) {
111
- await this.joinSession(sessionId);
112
- } else {
113
- await this.createSession();
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);
114
59
  }
115
-
116
- this.setupCommandHandlers();
117
- this.prompt();
118
60
  }
119
61
 
120
62
  async askQuestion(question) {
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "sam-coder-cli",
3
- "version": "1.0.32",
3
+ "version": "1.0.34",
4
4
  "description": "SAM-CODER: An animated command-line AI assistant with agency capabilities.",
5
5
  "main": "bin/agi-cli.js",
6
6
  "bin": {
7
7
  "sam-coder": "bin/agi-cli.js",
8
- "sam-coder-server": "bin/agi-cli.js --server"
8
+ "sam-coder-server": "bin/agi-cli.js --server",
9
+ "collaborate": "./bin/collaborate.js"
9
10
  },
10
11
  "scripts": {
11
12
  "start": "node ./bin/agi-cli.js"
@@ -21,8 +22,10 @@
21
22
  "license": "MIT",
22
23
  "dependencies": {
23
24
  "chalk": "^4.1.2",
25
+ "commander": "^11.0.0",
24
26
  "node-fetch": "^2.6.7",
25
27
  "ora": "^5.4.1",
28
+ "readline": "^1.3.0",
26
29
  "uuid": "^9.0.0",
27
30
  "ws": "^8.18.3"
28
31
  },