@supaku/agentfactory-cli 0.3.0 → 0.4.1

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.
Files changed (34) hide show
  1. package/dist/src/analyze-logs.d.ts +2 -2
  2. package/dist/src/analyze-logs.js +23 -194
  3. package/dist/src/cleanup.d.ts +2 -6
  4. package/dist/src/cleanup.d.ts.map +1 -1
  5. package/dist/src/cleanup.js +24 -225
  6. package/dist/src/lib/analyze-logs-runner.d.ts +47 -0
  7. package/dist/src/lib/analyze-logs-runner.d.ts.map +1 -0
  8. package/dist/src/lib/analyze-logs-runner.js +216 -0
  9. package/dist/src/lib/cleanup-runner.d.ts +28 -0
  10. package/dist/src/lib/cleanup-runner.d.ts.map +1 -0
  11. package/dist/src/lib/cleanup-runner.js +224 -0
  12. package/dist/src/lib/orchestrator-runner.d.ts +45 -0
  13. package/dist/src/lib/orchestrator-runner.d.ts.map +1 -0
  14. package/dist/src/lib/orchestrator-runner.js +144 -0
  15. package/dist/src/lib/queue-admin-runner.d.ts +30 -0
  16. package/dist/src/lib/queue-admin-runner.d.ts.map +1 -0
  17. package/dist/src/lib/queue-admin-runner.js +378 -0
  18. package/dist/src/lib/worker-fleet-runner.d.ts +28 -0
  19. package/dist/src/lib/worker-fleet-runner.d.ts.map +1 -0
  20. package/dist/src/lib/worker-fleet-runner.js +224 -0
  21. package/dist/src/lib/worker-runner.d.ts +31 -0
  22. package/dist/src/lib/worker-runner.d.ts.map +1 -0
  23. package/dist/src/lib/worker-runner.js +735 -0
  24. package/dist/src/orchestrator.d.ts +1 -1
  25. package/dist/src/orchestrator.js +42 -106
  26. package/dist/src/queue-admin.d.ts +3 -2
  27. package/dist/src/queue-admin.d.ts.map +1 -1
  28. package/dist/src/queue-admin.js +38 -360
  29. package/dist/src/worker-fleet.d.ts +1 -1
  30. package/dist/src/worker-fleet.js +23 -162
  31. package/dist/src/worker.d.ts +1 -0
  32. package/dist/src/worker.d.ts.map +1 -1
  33. package/dist/src/worker.js +33 -702
  34. package/package.json +28 -4
@@ -3,7 +3,7 @@
3
3
  * AgentFactory Worker Fleet Manager
4
4
  *
5
5
  * Spawns and manages multiple worker processes for parallel agent execution.
6
- * Each worker runs as a separate process with its own resources.
6
+ * Thin wrapper around the programmatic runner in ./lib/worker-fleet-runner.js.
7
7
  *
8
8
  * Usage:
9
9
  * af-worker-fleet [options]
@@ -19,38 +19,24 @@
19
19
  * WORKER_API_URL Coordinator API URL (required)
20
20
  * WORKER_API_KEY API key for authentication (required)
21
21
  */
22
- import { spawn } from 'child_process';
23
- import os from 'os';
24
22
  import path from 'path';
25
- import { fileURLToPath } from 'url';
23
+ import os from 'os';
26
24
  import { config as loadEnv } from 'dotenv';
27
25
  // Load environment variables from .env.local in CWD
28
26
  loadEnv({ path: path.resolve(process.cwd(), '.env.local') });
29
- // Resolve the directory of this script (for finding worker.js)
30
- const __filename = fileURLToPath(import.meta.url);
31
- const __dirname = path.dirname(__filename);
32
- // ANSI colors
27
+ import { runWorkerFleet } from './lib/worker-fleet-runner.js';
28
+ // ANSI colors (kept for help output)
33
29
  const colors = {
34
30
  reset: '\x1b[0m',
35
31
  red: '\x1b[31m',
36
32
  green: '\x1b[32m',
37
33
  yellow: '\x1b[33m',
38
- blue: '\x1b[34m',
39
- magenta: '\x1b[35m',
40
34
  cyan: '\x1b[36m',
41
- gray: '\x1b[90m',
42
35
  };
43
- // Worker color cycling
44
- const workerColors = [
45
- colors.cyan,
46
- colors.magenta,
47
- colors.yellow,
48
- colors.green,
49
- colors.blue,
50
- ];
51
36
  function parseArgs() {
52
37
  const args = process.argv.slice(2);
53
- let workers = parseInt(process.env.WORKER_FLEET_SIZE ?? '0', 10) || Math.max(1, Math.floor(os.cpus().length / 2));
38
+ let workers = parseInt(process.env.WORKER_FLEET_SIZE ?? '0', 10) ||
39
+ Math.max(1, Math.floor(os.cpus().length / 2));
54
40
  let capacity = parseInt(process.env.WORKER_CAPACITY ?? '3', 10);
55
41
  let dryRun = false;
56
42
  for (let i = 0; i < args.length; i++) {
@@ -101,146 +87,8 @@ ${colors.yellow}System Info:${colors.reset}
101
87
  Free RAM: ${Math.round(os.freemem() / 1024 / 1024 / 1024)} GB
102
88
  `);
103
89
  }
104
- function timestamp() {
105
- return new Date().toLocaleTimeString('en-US', { hour12: false });
106
- }
107
- function fleetLog(workerId, color, level, message) {
108
- const prefix = workerId !== null ? `[W${workerId.toString().padStart(2, '0')}]` : '[FLEET]';
109
- const levelColor = level === 'ERR' ? colors.red : level === 'WRN' ? colors.yellow : colors.gray;
110
- console.log(`${colors.gray}${timestamp()}${colors.reset} ${color}${prefix}${colors.reset} ${levelColor}${level}${colors.reset} ${message}`);
111
- }
112
- class WorkerFleet {
113
- workers = new Map();
114
- fleetConfig;
115
- shuttingDown = false;
116
- workerScript;
117
- constructor(fleetConfig) {
118
- this.fleetConfig = fleetConfig;
119
- // Use the compiled worker.js in the same directory
120
- this.workerScript = path.resolve(__dirname, 'worker.js');
121
- }
122
- async start() {
123
- const { workers, capacity, dryRun } = this.fleetConfig;
124
- const totalCapacity = workers * capacity;
125
- console.log(`
126
- ${colors.cyan}================================================================${colors.reset}
127
- ${colors.cyan} AgentFactory Worker Fleet Manager${colors.reset}
128
- ${colors.cyan}================================================================${colors.reset}
129
- Workers: ${colors.green}${workers}${colors.reset}
130
- Capacity/Worker: ${colors.green}${capacity}${colors.reset}
131
- Total Capacity: ${colors.green}${totalCapacity}${colors.reset} concurrent agents
132
-
133
- System:
134
- CPU Cores: ${os.cpus().length}
135
- Total RAM: ${Math.round(os.totalmem() / 1024 / 1024 / 1024)} GB
136
- Free RAM: ${Math.round(os.freemem() / 1024 / 1024 / 1024)} GB
137
- ${colors.cyan}================================================================${colors.reset}
138
- `);
139
- if (dryRun) {
140
- console.log(`${colors.yellow}Dry run mode - not starting workers${colors.reset}`);
141
- return;
142
- }
143
- // Set up shutdown handlers
144
- process.on('SIGINT', () => this.shutdown('SIGINT'));
145
- process.on('SIGTERM', () => this.shutdown('SIGTERM'));
146
- // Spawn workers with staggered start to avoid thundering herd
147
- for (let i = 0; i < workers; i++) {
148
- await this.spawnWorker(i);
149
- if (i < workers - 1) {
150
- await new Promise(resolve => setTimeout(resolve, 1000));
151
- }
152
- }
153
- fleetLog(null, colors.green, 'INF', `All ${workers} workers started`);
154
- // Keep the fleet manager running
155
- await new Promise(() => { });
156
- }
157
- async spawnWorker(id) {
158
- const color = workerColors[id % workerColors.length];
159
- const existingWorker = this.workers.get(id);
160
- const restartCount = existingWorker?.restartCount ?? 0;
161
- fleetLog(id, color, 'INF', `Starting worker (capacity: ${this.fleetConfig.capacity})${restartCount > 0 ? ` [restart #${restartCount}]` : ''}`);
162
- const workerProcess = spawn('node', [this.workerScript, '--capacity', String(this.fleetConfig.capacity)], {
163
- stdio: ['ignore', 'pipe', 'pipe'],
164
- env: {
165
- ...process.env,
166
- WORKER_FLEET_ID: String(id),
167
- },
168
- cwd: process.cwd(),
169
- });
170
- const workerInfo = {
171
- id,
172
- process: workerProcess,
173
- color,
174
- startedAt: new Date(),
175
- restartCount,
176
- };
177
- this.workers.set(id, workerInfo);
178
- // Handle stdout - prefix with worker ID
179
- workerProcess.stdout?.on('data', (data) => {
180
- const lines = data.toString().trim().split('\n');
181
- for (const line of lines) {
182
- if (line.trim()) {
183
- console.log(`${color}[W${id.toString().padStart(2, '0')}]${colors.reset} ${line}`);
184
- }
185
- }
186
- });
187
- // Handle stderr
188
- workerProcess.stderr?.on('data', (data) => {
189
- const lines = data.toString().trim().split('\n');
190
- for (const line of lines) {
191
- if (line.trim()) {
192
- console.log(`${color}[W${id.toString().padStart(2, '0')}]${colors.reset} ${colors.red}${line}${colors.reset}`);
193
- }
194
- }
195
- });
196
- // Handle worker exit
197
- workerProcess.on('exit', (code, signal) => {
198
- if (this.shuttingDown) {
199
- fleetLog(id, color, 'INF', `Worker stopped (code: ${code}, signal: ${signal})`);
200
- return;
201
- }
202
- fleetLog(id, color, 'WRN', `Worker exited unexpectedly (code: ${code}, signal: ${signal}) - restarting in 5s`);
203
- const worker = this.workers.get(id);
204
- if (worker) {
205
- worker.restartCount++;
206
- }
207
- setTimeout(() => {
208
- if (!this.shuttingDown) {
209
- this.spawnWorker(id);
210
- }
211
- }, 5000);
212
- });
213
- workerProcess.on('error', (err) => {
214
- fleetLog(id, color, 'ERR', `Worker error: ${err.message}`);
215
- });
216
- }
217
- async shutdown(signal) {
218
- if (this.shuttingDown)
219
- return;
220
- this.shuttingDown = true;
221
- console.log(`\n${colors.yellow}Received ${signal} - shutting down fleet...${colors.reset}`);
222
- for (const [id, worker] of this.workers) {
223
- fleetLog(id, worker.color, 'INF', 'Stopping worker...');
224
- worker.process.kill('SIGTERM');
225
- }
226
- // Wait for workers to exit (max 30 seconds)
227
- const timeout = setTimeout(() => {
228
- console.log(`${colors.red}Timeout waiting for workers - force killing${colors.reset}`);
229
- for (const worker of this.workers.values()) {
230
- worker.process.kill('SIGKILL');
231
- }
232
- process.exit(1);
233
- }, 30000);
234
- await Promise.all(Array.from(this.workers.values()).map((worker) => new Promise((resolve) => {
235
- worker.process.on('exit', () => resolve());
236
- })));
237
- clearTimeout(timeout);
238
- console.log(`${colors.green}All workers stopped${colors.reset}`);
239
- process.exit(0);
240
- }
241
- }
242
- // Main
243
- const fleetConfig = parseArgs();
90
+ // --- Main ---
91
+ const fleetArgs = parseArgs();
244
92
  if (!process.env.WORKER_API_URL) {
245
93
  console.error(`${colors.red}Error: WORKER_API_URL environment variable is required${colors.reset}`);
246
94
  process.exit(1);
@@ -249,8 +97,21 @@ if (!process.env.WORKER_API_KEY) {
249
97
  console.error(`${colors.red}Error: WORKER_API_KEY environment variable is required${colors.reset}`);
250
98
  process.exit(1);
251
99
  }
252
- const fleet = new WorkerFleet(fleetConfig);
253
- fleet.start().catch((err) => {
100
+ // Create AbortController for graceful shutdown
101
+ const controller = new AbortController();
102
+ process.on('SIGINT', () => controller.abort());
103
+ process.on('SIGTERM', () => controller.abort());
104
+ runWorkerFleet({
105
+ workers: fleetArgs.workers,
106
+ capacity: fleetArgs.capacity,
107
+ dryRun: fleetArgs.dryRun,
108
+ apiUrl: process.env.WORKER_API_URL,
109
+ apiKey: process.env.WORKER_API_KEY,
110
+ }, controller.signal)
111
+ .then(() => {
112
+ process.exit(0);
113
+ })
114
+ .catch((err) => {
254
115
  console.error(`${colors.red}Fleet error: ${err instanceof Error ? err.message : String(err)}${colors.reset}`);
255
116
  process.exit(1);
256
117
  });
@@ -3,6 +3,7 @@
3
3
  * AgentFactory Worker CLI
4
4
  *
5
5
  * Local worker that polls the coordinator for work and executes agents.
6
+ * Thin wrapper around the programmatic runner in ./lib/worker-runner.js.
6
7
  *
7
8
  * Usage:
8
9
  * af-worker [options]
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/worker.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;GAmBG"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/worker.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;GAoBG"}