sam-coder-cli 1.0.42 ā 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.
- package/bin/agi-cli.js +7 -77
- package/package.json +2 -8
- package/MULTIPLAYER.md +0 -112
- package/bin/ai-collaboration.js +0 -175
- package/bin/ai-team.js +0 -228
- package/bin/collaborate.js +0 -48
- package/bin/multiplayer-client.js +0 -896
- package/bin/multiplayer-mode.js +0 -276
- package/bin/multiplayer-server.js +0 -372
package/bin/agi-cli.js
CHANGED
|
@@ -3,14 +3,11 @@
|
|
|
3
3
|
const ui = require('./ui.js');
|
|
4
4
|
const readline = require('readline');
|
|
5
5
|
const path = require('path');
|
|
6
|
-
// Import MultiplayerMode at the top level to avoid reference errors
|
|
7
|
-
let MultiplayerMode;
|
|
8
6
|
const os = require('os');
|
|
9
7
|
const fs = require('fs').promises;
|
|
10
8
|
const { exec } = require('child_process');
|
|
11
9
|
const util = require('util');
|
|
12
10
|
const execAsync = util.promisify(exec);
|
|
13
|
-
// Import MultiplayerMode only when needed to avoid circular dependencies
|
|
14
11
|
|
|
15
12
|
// Configuration
|
|
16
13
|
const CONFIG_PATH = path.join(os.homedir(), '.sam-coder-config.json');
|
|
@@ -675,20 +672,10 @@ async function chat(rl, useToolCalling, initialModel) {
|
|
|
675
672
|
});
|
|
676
673
|
}
|
|
677
674
|
|
|
678
|
-
function askForMode(rl
|
|
675
|
+
function askForMode(rl) {
|
|
679
676
|
return new Promise((resolve) => {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
: 'Select mode (1 for tool calling, 2 for function calling): ';
|
|
683
|
-
|
|
684
|
-
rl.question(prompt, (answer) => {
|
|
685
|
-
const choice = answer.trim();
|
|
686
|
-
if (includeMultiplayer) {
|
|
687
|
-
if (choice === '3') resolve('multiplayer');
|
|
688
|
-
else resolve(choice === '1' ? 'tool' : 'function');
|
|
689
|
-
} else {
|
|
690
|
-
resolve(choice === '1');
|
|
691
|
-
}
|
|
677
|
+
rl.question('Select mode (1 for tool calling, 2 for function calling): ', (answer) => {
|
|
678
|
+
resolve(answer.trim() === '1');
|
|
692
679
|
});
|
|
693
680
|
});
|
|
694
681
|
}
|
|
@@ -752,21 +739,6 @@ async function start() {
|
|
|
752
739
|
output: process.stdout
|
|
753
740
|
});
|
|
754
741
|
|
|
755
|
-
// Check for server mode
|
|
756
|
-
if (process.argv.includes('--server')) {
|
|
757
|
-
try {
|
|
758
|
-
const port = parseInt(process.argv[process.argv.indexOf('--port') + 1]) || 8080;
|
|
759
|
-
const MultiplayerServer = require('./multiplayer-server');
|
|
760
|
-
const server = new MultiplayerServer(port);
|
|
761
|
-
await server.start();
|
|
762
|
-
console.log(`Multiplayer server started on ws://localhost:${server.port}`);
|
|
763
|
-
return;
|
|
764
|
-
} catch (error) {
|
|
765
|
-
console.error('Failed to start multiplayer server:', error.message);
|
|
766
|
-
process.exit(1);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
|
|
770
742
|
try {
|
|
771
743
|
let config = await readConfig();
|
|
772
744
|
if (!config || !config.OPENROUTER_API_KEY) {
|
|
@@ -776,62 +748,20 @@ async function start() {
|
|
|
776
748
|
MODEL = config.MODEL || 'deepseek/deepseek-chat-v3-0324:free';
|
|
777
749
|
|
|
778
750
|
OPENROUTER_API_KEY = config.OPENROUTER_API_KEY;
|
|
779
|
-
|
|
780
751
|
if (config.isPro && config.customApiBase) {
|
|
781
752
|
API_BASE_URL = config.customApiBase;
|
|
782
753
|
console.log(`š Using Pro Plan custom endpoint: ${API_BASE_URL}`);
|
|
783
754
|
}
|
|
784
755
|
|
|
785
756
|
ui.showHeader();
|
|
786
|
-
|
|
787
|
-
// Multiplayer mode via CLI flag
|
|
788
|
-
if (process.argv.includes('--multiplayer')) {
|
|
789
|
-
// Lazy load MultiplayerMode to avoid circular dependencies
|
|
790
|
-
if (!MultiplayerMode) {
|
|
791
|
-
MultiplayerMode = require('./multiplayer-mode');
|
|
792
|
-
}
|
|
793
|
-
try {
|
|
794
|
-
const multiplayerMode = new MultiplayerMode({
|
|
795
|
-
rl,
|
|
796
|
-
model: MODEL,
|
|
797
|
-
serverUrl: process.env.MP_SERVER_URL || 'ws://localhost:8080'
|
|
798
|
-
});
|
|
799
|
-
await multiplayerMode.start();
|
|
800
|
-
return;
|
|
801
|
-
} catch (error) {
|
|
802
|
-
console.error('Failed to start multiplayer mode:', error);
|
|
803
|
-
process.exit(1);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
// Standard single-agent mode
|
|
808
757
|
console.log('Select Mode:');
|
|
809
758
|
console.log('1. Tool Calling (for models that support it)');
|
|
810
759
|
console.log('2. Function Calling (legacy)');
|
|
811
|
-
console.log('3. Multiplayer Mode (collaborate with other agents)');
|
|
812
760
|
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
MultiplayerMode = require('./multiplayer-mode');
|
|
818
|
-
}
|
|
819
|
-
try {
|
|
820
|
-
const multiplayerMode = new MultiplayerMode({
|
|
821
|
-
rl,
|
|
822
|
-
model: MODEL,
|
|
823
|
-
serverUrl: process.env.MP_SERVER_URL || 'ws://localhost:8080'
|
|
824
|
-
});
|
|
825
|
-
await multiplayerMode.start();
|
|
826
|
-
} catch (error) {
|
|
827
|
-
console.error('Failed to initialize multiplayer mode:', error);
|
|
828
|
-
process.exit(1);
|
|
829
|
-
}
|
|
830
|
-
} else {
|
|
831
|
-
const useToolCalling = mode === 'tool';
|
|
832
|
-
ui.showResponse(`\nStarting in ${useToolCalling ? 'Tool Calling' : 'Function Calling'} mode...\n`);
|
|
833
|
-
await chat(rl, useToolCalling, MODEL);
|
|
834
|
-
}
|
|
761
|
+
const useToolCalling = await askForMode(rl);
|
|
762
|
+
ui.showResponse(`\nStarting in ${useToolCalling ? 'Tool Calling' : 'Function Calling'} mode...\n`);
|
|
763
|
+
|
|
764
|
+
await chat(rl, useToolCalling, MODEL);
|
|
835
765
|
} catch (error) {
|
|
836
766
|
ui.showError(error);
|
|
837
767
|
rl.close();
|
package/package.json
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sam-coder-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.44",
|
|
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
|
-
"sam-coder": "bin/agi-cli.js"
|
|
8
|
-
"sam-coder-server": "bin/agi-cli.js --server",
|
|
9
|
-
"collaborate": "./bin/collaborate.js"
|
|
7
|
+
"sam-coder": "bin/agi-cli.js"
|
|
10
8
|
},
|
|
11
9
|
"scripts": {
|
|
12
10
|
"start": "node ./bin/agi-cli.js"
|
|
@@ -22,11 +20,7 @@
|
|
|
22
20
|
"license": "MIT",
|
|
23
21
|
"dependencies": {
|
|
24
22
|
"chalk": "^4.1.2",
|
|
25
|
-
"commander": "^11.0.0",
|
|
26
|
-
"node-fetch": "^2.6.7",
|
|
27
23
|
"ora": "^5.4.1",
|
|
28
|
-
"readline": "^1.3.0",
|
|
29
|
-
"uuid": "^9.0.0",
|
|
30
24
|
"ws": "^8.18.3"
|
|
31
25
|
},
|
|
32
26
|
"devDependencies": {
|
package/MULTIPLAYER.md
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# Multiplayer Mode for SAM-CODER
|
|
2
|
-
|
|
3
|
-
This guide explains how to use the Multiplayer Mode to collaborate with multiple AI agents in real-time.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Host or join multiplayer sessions
|
|
8
|
-
- Connect 2-4 AI agents in a single session
|
|
9
|
-
- Each agent can have a unique name and role
|
|
10
|
-
- Real-time chat and task coordination
|
|
11
|
-
- Shared work history and task assignment
|
|
12
|
-
- Support for different models/endpoints per agent
|
|
13
|
-
|
|
14
|
-
## Quick Start
|
|
15
|
-
|
|
16
|
-
1. First, install the required dependencies:
|
|
17
|
-
```bash
|
|
18
|
-
npm install
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
2. Start the multiplayer server in a separate terminal:
|
|
22
|
-
```bash
|
|
23
|
-
node bin/multiplayer-server.js
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
3. In a new terminal, start the first agent (host):
|
|
27
|
-
```bash
|
|
28
|
-
node bin/agi-cli.js --multiplayer
|
|
29
|
-
```
|
|
30
|
-
- Press Enter to create a new session
|
|
31
|
-
- Note the session ID shown in the console
|
|
32
|
-
|
|
33
|
-
4. In another terminal, start additional agents (up to 3 more):
|
|
34
|
-
```bash
|
|
35
|
-
node bin/agi-cli.js --multiplayer
|
|
36
|
-
```
|
|
37
|
-
- Enter the session ID from step 3 to join
|
|
38
|
-
|
|
39
|
-
## Multiplayer Commands
|
|
40
|
-
|
|
41
|
-
Once in a multiplayer session, you can use these commands:
|
|
42
|
-
|
|
43
|
-
- `/name [new_name]` - Set or show your agent's name
|
|
44
|
-
- `/role [role]` - Set or show your agent's role
|
|
45
|
-
- `/work [description]` - Update your work status
|
|
46
|
-
- `/task [agent_name] [task]` - Assign a task to another agent
|
|
47
|
-
- `/list` - List all agents in the session
|
|
48
|
-
- `/help` - Show available commands
|
|
49
|
-
- `/exit` - Leave the session
|
|
50
|
-
|
|
51
|
-
## Agent Coordination
|
|
52
|
-
|
|
53
|
-
### Work History
|
|
54
|
-
- All agents can see updates to the shared work history
|
|
55
|
-
- Use `/work` to update what you're working on
|
|
56
|
-
- The work history helps agents coordinate and avoid duplicate work
|
|
57
|
-
|
|
58
|
-
### Task Assignment
|
|
59
|
-
- Use `/task` to assign specific tasks to other agents
|
|
60
|
-
- Example: `/task Coder1 Implement the login function`
|
|
61
|
-
- Assigned tasks appear in the target agent's console
|
|
62
|
-
|
|
63
|
-
### Chat
|
|
64
|
-
- Type any message to send it to all agents in the session
|
|
65
|
-
- Use this to coordinate, ask questions, or share information
|
|
66
|
-
|
|
67
|
-
## Advanced Usage
|
|
68
|
-
|
|
69
|
-
### Custom Server URL
|
|
70
|
-
By default, the client connects to `ws://localhost:8080`. To use a different server:
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
MP_SERVER_URL=ws://your-server-address:port node bin/agi-cli.js --multiplayer
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Different Models per Agent
|
|
77
|
-
Each agent can use a different model by setting the `MODEL` environment variable:
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
MODEL=anthropic/claude-2 node bin/agi-cli.js --multiplayer
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Troubleshooting
|
|
84
|
-
|
|
85
|
-
### Connection Issues
|
|
86
|
-
- Ensure the multiplayer server is running
|
|
87
|
-
- Check that the server URL is correct
|
|
88
|
-
- Verify that your firewall allows WebSocket connections on the specified port
|
|
89
|
-
|
|
90
|
-
### Session Full
|
|
91
|
-
- Each session supports up to 4 agents
|
|
92
|
-
- Create a new session if you need more agents
|
|
93
|
-
|
|
94
|
-
### Agent Names
|
|
95
|
-
- Agent names must be unique within a session
|
|
96
|
-
- Use `/name` to change your agent's name if needed
|
|
97
|
-
|
|
98
|
-
## Example Workflow
|
|
99
|
-
|
|
100
|
-
1. Agent 1 creates a session and becomes the host
|
|
101
|
-
2. Agent 2 joins the session with `/join <session-id>`
|
|
102
|
-
3. Agents assign roles:
|
|
103
|
-
- Agent 1: `/role Backend Developer`
|
|
104
|
-
- Agent 2: `/role Frontend Developer`
|
|
105
|
-
4. They coordinate work:
|
|
106
|
-
- Agent 1: `/work Implementing user authentication API`
|
|
107
|
-
- Agent 2: `/work Creating login form UI`
|
|
108
|
-
5. They can assign tasks to each other:
|
|
109
|
-
- Agent 1: `/task Frontend Add form validation`
|
|
110
|
-
- Agent 2: `/task Backend Add rate limiting to auth endpoint`
|
|
111
|
-
|
|
112
|
-
Enjoy collaborating with multiple AI agents in real-time!
|
package/bin/ai-collaboration.js
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
// Import dependencies at runtime to avoid circular dependencies
|
|
2
|
-
let callOpenRouter;
|
|
3
|
-
let MultiplayerClient;
|
|
4
|
-
const readline = require('readline');
|
|
5
|
-
const chalk = require('chalk');
|
|
6
|
-
const { v4: uuidv4 } = require('uuid');
|
|
7
|
-
|
|
8
|
-
// Flag to track if MultiplayerClient is being required to prevent infinite loops
|
|
9
|
-
let isRequiringMultiplayerClient = false;
|
|
10
|
-
|
|
11
|
-
// Lazy load dependencies to avoid circular dependencies
|
|
12
|
-
function getCallOpenRouter() {
|
|
13
|
-
if (!callOpenRouter) {
|
|
14
|
-
callOpenRouter = require('./agi-cli').callOpenRouter;
|
|
15
|
-
}
|
|
16
|
-
return callOpenRouter;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function getMultiplayerClient() {
|
|
20
|
-
if (!MultiplayerClient && !isRequiringMultiplayerClient) {
|
|
21
|
-
try {
|
|
22
|
-
isRequiringMultiplayerClient = true;
|
|
23
|
-
const mc = require('./multiplayer-client');
|
|
24
|
-
MultiplayerClient = mc.MultiplayerClient;
|
|
25
|
-
} finally {
|
|
26
|
-
isRequiringMultiplayerClient = false;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
if (!MultiplayerClient) {
|
|
30
|
-
throw new Error('Failed to load MultiplayerClient');
|
|
31
|
-
}
|
|
32
|
-
return MultiplayerClient;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// System prompt for AI team collaboration
|
|
36
|
-
const TEAM_COLLABORATION_PROMPT = `You are an AI team facilitator that helps coordinate multiple AI agents working together on a project.
|
|
37
|
-
|
|
38
|
-
Your responsibilities include:
|
|
39
|
-
1. Understanding the project requirements from the host
|
|
40
|
-
2. Breaking down the project into clear, actionable tasks
|
|
41
|
-
3. Assigning tasks to appropriate team members based on their roles
|
|
42
|
-
4. Monitoring progress and coordinating between team members
|
|
43
|
-
|
|
44
|
-
When the host provides a project idea (e.g., "create a calculator"), you should:
|
|
45
|
-
1. Analyze the requirements
|
|
46
|
-
2. Break it down into logical components
|
|
47
|
-
3. Create a task list with clear assignments
|
|
48
|
-
4. Provide a summary of the plan
|
|
49
|
-
|
|
50
|
-
Respond in markdown format with clear sections for each part of your response.`;
|
|
51
|
-
|
|
52
|
-
class AITeam {
|
|
53
|
-
constructor(options = {}) {
|
|
54
|
-
const MultiplayerClient = getMultiplayerClient();
|
|
55
|
-
this.client = new MultiplayerClient({
|
|
56
|
-
name: options.name || `Agent-${uuidv4().substr(0, 4)}`,
|
|
57
|
-
role: options.role || 'DEVELOPER',
|
|
58
|
-
model: options.model || 'deepseek/deepseek-chat-v3-0324:free',
|
|
59
|
-
rl: options.rl
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
this.rl = options.rl || readline.createInterface({
|
|
63
|
-
input: process.stdin,
|
|
64
|
-
output: process.stdout
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
this.conversation = [
|
|
68
|
-
{ role: 'system', content: TEAM_COLLABORATION_PROMPT }
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
this.setupEventHandlers();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
setupEventHandlers() {
|
|
75
|
-
this.client.on('connected', () => {
|
|
76
|
-
console.log(chalk.green('ā
Connected to multiplayer server'));
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
this.client.on('disconnected', () => {
|
|
80
|
-
console.log(chalk.yellow('Disconnected from multiplayer server'));
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
this.client.on('error', (error) => {
|
|
84
|
-
console.error(chalk.red('Error:'), error.message);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
this.client.on('session_joined', async (data) => {
|
|
88
|
-
console.log(chalk.green(`\nš Joined session ${data.sessionId} as ${this.client.name}`));
|
|
89
|
-
console.log(chalk.blue(`Role: ${this.client.role}`));
|
|
90
|
-
|
|
91
|
-
if (data.isHost) {
|
|
92
|
-
console.log('\nAs the host, you can now enter a project prompt (e.g., "create a calculator"):');
|
|
93
|
-
await this.promptForProject();
|
|
94
|
-
} else {
|
|
95
|
-
console.log('\nWaiting for host to start a project...');
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
this.client.on('chat_message', async (message) => {
|
|
100
|
-
if (message.clientId !== this.client.clientId) {
|
|
101
|
-
console.log(`\nš¬ ${message.clientName || 'Unknown'}: ${message.text}`);
|
|
102
|
-
|
|
103
|
-
// If we receive a task assignment, process it
|
|
104
|
-
if (message.task) {
|
|
105
|
-
await this.processTask(message.task);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async start(sessionId = null) {
|
|
112
|
-
let serverId = null;
|
|
113
|
-
let actualSessionId = sessionId;
|
|
114
|
-
|
|
115
|
-
// Check if sessionId contains server information (format: serverId:sessionId)
|
|
116
|
-
if (sessionId && sessionId.includes(':')) {
|
|
117
|
-
[serverId, actualSessionId] = sessionId.split(':');
|
|
118
|
-
console.log(chalk.blue(`Attempting to connect to server: ${serverId}`));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Connect to the server first
|
|
122
|
-
try {
|
|
123
|
-
await this.client.connect(serverId);
|
|
124
|
-
|
|
125
|
-
if (actualSessionId) {
|
|
126
|
-
console.log(`Joining session ${actualSessionId}...`);
|
|
127
|
-
await this.client.joinSession(actualSessionId);
|
|
128
|
-
} else {
|
|
129
|
-
console.log('Creating new session...');
|
|
130
|
-
const newSessionId = await this.client.createSession();
|
|
131
|
-
console.log(chalk.green(`ā
Created new session: ${newSessionId}`));
|
|
132
|
-
console.log('Share this ID with others to collaborate!');
|
|
133
|
-
console.log(chalk.yellow(`To join this session, use: ${serverId || 'localhost:8080'}:${newSessionId}`));
|
|
134
|
-
}
|
|
135
|
-
} catch (error) {
|
|
136
|
-
console.error(chalk.red('Failed to connect to server:'), error.message);
|
|
137
|
-
process.exit(1);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Start chat input loop
|
|
141
|
-
this.rl.on('line', async (input) => {
|
|
142
|
-
if (input.trim()) {
|
|
143
|
-
if (this.client.isHost) {
|
|
144
|
-
await this.handleHostInput(input.trim());
|
|
145
|
-
} else {
|
|
146
|
-
await this.handleTeamMemberInput(input.trim());
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async handleHostInput(input) {
|
|
153
|
-
// Add user message to conversation
|
|
154
|
-
this.conversation.push({ role: 'user', content: input });
|
|
155
|
-
|
|
156
|
-
// Get AI response
|
|
157
|
-
const callOpenRouter = getCallOpenRouter();
|
|
158
|
-
const response = await callOpenRouter(this.conversation, this.client.model);
|
|
159
|
-
const aiMessage = response.choices[0].message;
|
|
160
|
-
|
|
161
|
-
// Add AI response to conversation
|
|
162
|
-
this.conversation.push(aiMessage);
|
|
163
|
-
|
|
164
|
-
// Display response
|
|
165
|
-
console.log(`\nš¤ ${aiMessage.content}\n`);
|
|
166
|
-
|
|
167
|
-
// If AI suggests tasks, assign them to team members
|
|
168
|
-
if (aiMessage.tool_calls) {
|
|
169
|
-
await this.handleToolCalls(aiMessage.tool_calls);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Show prompt for next input
|
|
173
|
-
this.showPrompt();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async handleTeamMemberInput(input) {
|
|
177
|
-
// For team members, just send chat messages for now
|
|
178
|
-
this.client.sendChatMessage(input);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
async handleToolCalls(toolCalls) {
|
|
182
|
-
for (const toolCall of toolCalls) {
|
|
183
|
-
if (toolCall.function.name === 'assign_task') {
|
|
184
|
-
const args = JSON.parse(toolCall.function.arguments);
|
|
185
|
-
await this.assignTask(args.role, args.task);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
async assignTask(role, task) {
|
|
191
|
-
console.log(chalk.yellow(`\nš Task for ${role}: ${task}`));
|
|
192
|
-
|
|
193
|
-
// In a real implementation, this would find the appropriate team member
|
|
194
|
-
// and assign them the task. For now, we'll just log it.
|
|
195
|
-
this.client.sendChatMessage(`Task assigned to ${role}: ${task}`, {
|
|
196
|
-
task: { role, description: task }
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
async processTask(task) {
|
|
201
|
-
console.log(chalk.blue(`\nš Task received: ${task.description}`));
|
|
202
|
-
|
|
203
|
-
// Process the task using the AGI-CLI's tool calling system
|
|
204
|
-
const callOpenRouter = getCallOpenRouter();
|
|
205
|
-
const response = await callOpenRouter([
|
|
206
|
-
{ role: 'system', content: `You are an AI assistant working on a task: ${task.description}` },
|
|
207
|
-
{ role: 'user', content: 'Please complete this task step by step.' }
|
|
208
|
-
], this.client.model, true);
|
|
209
|
-
|
|
210
|
-
const result = response.choices[0].message.content;
|
|
211
|
-
console.log(chalk.green('ā
Task completed!'));
|
|
212
|
-
console.log(result);
|
|
213
|
-
|
|
214
|
-
// Notify the team of task completion
|
|
215
|
-
this.client.sendChatMessage(`Completed task: ${task.description}`);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
showPrompt() {
|
|
219
|
-
const prefix = this.client.isHost ? 'š Host' : 'š¤ You';
|
|
220
|
-
process.stdout.write(`\n${prefix} > `);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
async promptForProject() {
|
|
224
|
-
this.showPrompt();
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
module.exports = AITeam;
|