@supaku/agentfactory-cli 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Supaku
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentFactory CLI
4
+ *
5
+ * Entry point for the agentfactory command.
6
+ * Dispatches to sub-commands based on first argument.
7
+ */
8
+ declare const command: string;
9
+ declare function printHelp(): void;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,QAAA,MAAM,OAAO,QAAkB,CAAA;AAE/B,iBAAS,SAAS,IAAI,IAAI,CAgBzB"}
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * AgentFactory CLI
5
+ *
6
+ * Entry point for the agentfactory command.
7
+ * Dispatches to sub-commands based on first argument.
8
+ */
9
+ const command = process.argv[2];
10
+ function printHelp() {
11
+ console.log(`
12
+ AgentFactory CLI — Multi-agent fleet management for coding agents
13
+
14
+ Usage:
15
+ agentfactory <command> [options]
16
+
17
+ Commands:
18
+ orchestrator Spawn concurrent agents on backlog issues
19
+ worker Start a remote worker that polls for queued work
20
+ help Show this help message
21
+
22
+ Run 'agentfactory <command> --help' for command-specific options.
23
+
24
+ Learn more: https://github.com/supaku/agentfactory
25
+ `);
26
+ }
27
+ switch (command) {
28
+ case 'orchestrator':
29
+ import('./orchestrator');
30
+ break;
31
+ case 'worker':
32
+ import('./worker');
33
+ break;
34
+ case 'help':
35
+ case '--help':
36
+ case '-h':
37
+ case undefined:
38
+ printHelp();
39
+ break;
40
+ default:
41
+ console.error(`Unknown command: ${command}`);
42
+ printHelp();
43
+ process.exit(1);
44
+ }
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentFactory Orchestrator CLI
4
+ *
5
+ * Local script to spawn concurrent coding agents on backlog issues.
6
+ *
7
+ * Usage:
8
+ * af-orchestrator [options]
9
+ *
10
+ * Options:
11
+ * --project <name> Filter issues by project name
12
+ * --max <number> Maximum concurrent agents (default: 3)
13
+ * --single <id> Process a single issue by ID
14
+ * --no-wait Don't wait for agents to complete
15
+ * --dry-run Show what would be done without executing
16
+ *
17
+ * Environment:
18
+ * LINEAR_API_KEY Required API key for Linear authentication
19
+ */
20
+ export {};
21
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentFactory Orchestrator CLI
4
+ *
5
+ * Local script to spawn concurrent coding agents on backlog issues.
6
+ *
7
+ * Usage:
8
+ * af-orchestrator [options]
9
+ *
10
+ * Options:
11
+ * --project <name> Filter issues by project name
12
+ * --max <number> Maximum concurrent agents (default: 3)
13
+ * --single <id> Process a single issue by ID
14
+ * --no-wait Don't wait for agents to complete
15
+ * --dry-run Show what would be done without executing
16
+ *
17
+ * Environment:
18
+ * LINEAR_API_KEY Required API key for Linear authentication
19
+ */
20
+ import path from 'path';
21
+ import { execSync } from 'child_process';
22
+ import { config } from 'dotenv';
23
+ // Load environment variables from .env.local
24
+ config({ path: path.resolve(process.cwd(), '.env.local') });
25
+ import { createOrchestrator } from '@supaku/agentfactory';
26
+ function getGitRoot() {
27
+ try {
28
+ return execSync('git rev-parse --show-toplevel', {
29
+ encoding: 'utf-8',
30
+ stdio: ['pipe', 'pipe', 'pipe'],
31
+ }).trim();
32
+ }
33
+ catch {
34
+ return process.cwd();
35
+ }
36
+ }
37
+ function parseArgs() {
38
+ const args = process.argv.slice(2);
39
+ const result = {
40
+ project: undefined,
41
+ max: 3,
42
+ single: undefined,
43
+ wait: true,
44
+ dryRun: false,
45
+ };
46
+ for (let i = 0; i < args.length; i++) {
47
+ const arg = args[i];
48
+ switch (arg) {
49
+ case '--project':
50
+ result.project = args[++i];
51
+ break;
52
+ case '--max':
53
+ result.max = parseInt(args[++i], 10);
54
+ break;
55
+ case '--single':
56
+ result.single = args[++i];
57
+ break;
58
+ case '--no-wait':
59
+ result.wait = false;
60
+ break;
61
+ case '--dry-run':
62
+ result.dryRun = true;
63
+ break;
64
+ case '--help':
65
+ case '-h':
66
+ printHelp();
67
+ process.exit(0);
68
+ }
69
+ }
70
+ return result;
71
+ }
72
+ function printHelp() {
73
+ console.log(`
74
+ AgentFactory Orchestrator — Multi-agent fleet management for coding agents
75
+
76
+ Usage:
77
+ af-orchestrator [options]
78
+
79
+ Options:
80
+ --project <name> Filter issues by project name
81
+ --max <number> Maximum concurrent agents (default: 3)
82
+ --single <id> Process a single issue by ID
83
+ --no-wait Don't wait for agents to complete
84
+ --dry-run Show what would be done without executing
85
+ --help, -h Show this help message
86
+
87
+ Environment:
88
+ LINEAR_API_KEY Required API key for Linear authentication
89
+
90
+ Examples:
91
+ # Process up to 3 backlog issues from a project
92
+ af-orchestrator --project MyProject
93
+
94
+ # Process a specific issue
95
+ af-orchestrator --single PROJ-123
96
+
97
+ # Preview what issues would be processed
98
+ af-orchestrator --project MyProject --dry-run
99
+ `);
100
+ }
101
+ function formatDuration(ms) {
102
+ const seconds = Math.floor(ms / 1000);
103
+ const minutes = Math.floor(seconds / 60);
104
+ const hours = Math.floor(minutes / 60);
105
+ if (hours > 0) {
106
+ return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
107
+ }
108
+ if (minutes > 0) {
109
+ return `${minutes}m ${seconds % 60}s`;
110
+ }
111
+ return `${seconds}s`;
112
+ }
113
+ async function main() {
114
+ const args = parseArgs();
115
+ if (!process.env.LINEAR_API_KEY) {
116
+ console.error('Error: LINEAR_API_KEY environment variable is required');
117
+ process.exit(1);
118
+ }
119
+ console.log('AgentFactory Orchestrator');
120
+ console.log('========================');
121
+ console.log(`Project: ${args.project ?? 'All'}`);
122
+ console.log(`Max concurrent: ${args.max}`);
123
+ console.log(`Dry run: ${args.dryRun}`);
124
+ console.log('');
125
+ const gitRoot = getGitRoot();
126
+ const orchestrator = createOrchestrator({
127
+ project: args.project,
128
+ maxConcurrent: args.max,
129
+ worktreePath: path.resolve(gitRoot, '.worktrees'),
130
+ }, {
131
+ onIssueSelected: (issue) => {
132
+ console.log(`Selected: ${issue.identifier} - ${issue.title}`);
133
+ console.log(` URL: ${issue.url}`);
134
+ console.log(` Labels: ${issue.labels.join(', ') || 'none'}`);
135
+ },
136
+ onAgentStart: (agent) => {
137
+ console.log(`Agent started: ${agent.identifier} (PID: ${agent.pid})`);
138
+ console.log(` Worktree: ${agent.worktreePath}`);
139
+ },
140
+ onAgentComplete: (agent) => {
141
+ const duration = agent.completedAt
142
+ ? formatDuration(agent.completedAt.getTime() - agent.startedAt.getTime())
143
+ : 'unknown';
144
+ console.log(`Agent completed: ${agent.identifier} (${duration})`);
145
+ },
146
+ onAgentError: (agent, error) => {
147
+ console.error(`Agent failed: ${agent.identifier}`);
148
+ console.error(` Error: ${error.message}`);
149
+ },
150
+ onAgentIncomplete: (agent) => {
151
+ const duration = agent.completedAt
152
+ ? formatDuration(agent.completedAt.getTime() - agent.startedAt.getTime())
153
+ : 'unknown';
154
+ console.warn(`Agent incomplete: ${agent.identifier} (${duration})`);
155
+ console.warn(` Reason: ${agent.incompleteReason ?? 'unknown'}`);
156
+ console.warn(` Worktree preserved: ${agent.worktreePath}`);
157
+ },
158
+ });
159
+ try {
160
+ if (args.single) {
161
+ console.log(`Processing single issue: ${args.single}`);
162
+ if (args.dryRun) {
163
+ console.log('[DRY RUN] Would spawn agent for:', args.single);
164
+ return;
165
+ }
166
+ await orchestrator.spawnAgentForIssue(args.single);
167
+ console.log(`Agent spawned for ${args.single}`);
168
+ if (args.wait) {
169
+ console.log('Waiting for agent to complete...');
170
+ await orchestrator.waitForAll();
171
+ }
172
+ return;
173
+ }
174
+ if (args.dryRun) {
175
+ const issues = await orchestrator.getBacklogIssues();
176
+ if (issues.length === 0) {
177
+ console.log('No backlog issues found');
178
+ return;
179
+ }
180
+ console.log(`[DRY RUN] Would process ${issues.length} issue(s):`);
181
+ for (const issue of issues) {
182
+ console.log(` - ${issue.identifier}: ${issue.title}`);
183
+ console.log(` Priority: ${issue.priority || 'none'}`);
184
+ console.log(` Labels: ${issue.labels.join(', ') || 'none'}`);
185
+ }
186
+ return;
187
+ }
188
+ const result = await orchestrator.run();
189
+ console.log('');
190
+ console.log('Orchestrator started');
191
+ console.log(` Agents spawned: ${result.agents.length}`);
192
+ console.log(` Errors: ${result.errors.length}`);
193
+ if (result.errors.length > 0) {
194
+ console.log('');
195
+ console.log('Errors:');
196
+ for (const { issueId, error } of result.errors) {
197
+ console.log(` ${issueId}: ${error.message}`);
198
+ }
199
+ }
200
+ if (args.wait && result.agents.length > 0) {
201
+ console.log('');
202
+ console.log('Waiting for all agents to complete...');
203
+ process.on('SIGINT', () => {
204
+ console.log('');
205
+ console.log('Received SIGINT, stopping agents...');
206
+ orchestrator.stopAll();
207
+ process.exit(1);
208
+ });
209
+ const completedAgents = await orchestrator.waitForAll();
210
+ console.log('');
211
+ console.log('All agents completed');
212
+ console.log('Results:');
213
+ for (const agent of completedAgents) {
214
+ const duration = agent.completedAt
215
+ ? formatDuration(agent.completedAt.getTime() - agent.startedAt.getTime())
216
+ : 'unknown';
217
+ const status = agent.status === 'completed' ? 'SUCCESS' : 'FAILED';
218
+ console.log(` ${agent.identifier}: ${status} (${duration})`);
219
+ }
220
+ }
221
+ }
222
+ catch (error) {
223
+ console.error('Orchestrator failed:', error instanceof Error ? error.message : error);
224
+ process.exit(1);
225
+ }
226
+ }
227
+ main().catch((error) => {
228
+ console.error('Fatal error:', error);
229
+ process.exit(1);
230
+ });
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentFactory Worker CLI
4
+ *
5
+ * Starts a remote worker that polls the Redis work queue
6
+ * and processes assigned agent sessions.
7
+ *
8
+ * Usage:
9
+ * af-worker [options]
10
+ *
11
+ * Options:
12
+ * --capacity <number> Maximum concurrent agents (default: 2)
13
+ * --api-url <url> Agent API URL for activity proxying
14
+ * --api-key <key> API key for worker authentication
15
+ *
16
+ * Environment:
17
+ * LINEAR_API_KEY Required API key for Linear authentication
18
+ * REDIS_URL Required for work queue polling
19
+ * WORKER_API_URL Agent API URL (alternative to --api-url)
20
+ * WORKER_API_KEY API key (alternative to --api-key)
21
+ */
22
+ export {};
23
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/worker.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;GAmBG"}
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentFactory Worker CLI
4
+ *
5
+ * Starts a remote worker that polls the Redis work queue
6
+ * and processes assigned agent sessions.
7
+ *
8
+ * Usage:
9
+ * af-worker [options]
10
+ *
11
+ * Options:
12
+ * --capacity <number> Maximum concurrent agents (default: 2)
13
+ * --api-url <url> Agent API URL for activity proxying
14
+ * --api-key <key> API key for worker authentication
15
+ *
16
+ * Environment:
17
+ * LINEAR_API_KEY Required API key for Linear authentication
18
+ * REDIS_URL Required for work queue polling
19
+ * WORKER_API_URL Agent API URL (alternative to --api-url)
20
+ * WORKER_API_KEY API key (alternative to --api-key)
21
+ */
22
+ import path from 'path';
23
+ import { config } from 'dotenv';
24
+ // Load environment variables
25
+ config({ path: path.resolve(process.cwd(), '.env.local') });
26
+ function parseArgs() {
27
+ const args = process.argv.slice(2);
28
+ const result = {
29
+ capacity: 2,
30
+ apiUrl: process.env.WORKER_API_URL,
31
+ apiKey: process.env.WORKER_API_KEY,
32
+ };
33
+ for (let i = 0; i < args.length; i++) {
34
+ const arg = args[i];
35
+ switch (arg) {
36
+ case '--capacity':
37
+ result.capacity = parseInt(args[++i], 10);
38
+ break;
39
+ case '--api-url':
40
+ result.apiUrl = args[++i];
41
+ break;
42
+ case '--api-key':
43
+ result.apiKey = args[++i];
44
+ break;
45
+ case '--help':
46
+ case '-h':
47
+ printHelp();
48
+ process.exit(0);
49
+ }
50
+ }
51
+ return result;
52
+ }
53
+ function printHelp() {
54
+ console.log(`
55
+ AgentFactory Worker — Remote agent worker for distributed processing
56
+
57
+ Usage:
58
+ af-worker [options]
59
+
60
+ Options:
61
+ --capacity <number> Maximum concurrent agents (default: 2)
62
+ --api-url <url> Agent API URL for activity proxying
63
+ --api-key <key> API key for worker authentication
64
+ --help, -h Show this help message
65
+
66
+ Environment:
67
+ LINEAR_API_KEY Required API key for Linear authentication
68
+ REDIS_URL Required for work queue polling
69
+ WORKER_API_URL Agent API URL (alternative to --api-url)
70
+ WORKER_API_KEY API key (alternative to --api-key)
71
+ `);
72
+ }
73
+ async function main() {
74
+ const args = parseArgs();
75
+ if (!process.env.LINEAR_API_KEY) {
76
+ console.error('Error: LINEAR_API_KEY environment variable is required');
77
+ process.exit(1);
78
+ }
79
+ if (!process.env.REDIS_URL) {
80
+ console.error('Error: REDIS_URL environment variable is required for worker mode');
81
+ process.exit(1);
82
+ }
83
+ console.log('AgentFactory Worker');
84
+ console.log('===================');
85
+ console.log(`Capacity: ${args.capacity}`);
86
+ console.log(`API URL: ${args.apiUrl ?? 'not configured'}`);
87
+ console.log('');
88
+ console.log('Worker started. Polling for work...');
89
+ console.log('Press Ctrl+C to stop.');
90
+ // Keep process alive
91
+ process.on('SIGINT', () => {
92
+ console.log('');
93
+ console.log('Worker shutting down...');
94
+ process.exit(0);
95
+ });
96
+ // TODO: Implement worker polling loop
97
+ // This is a placeholder — the full implementation involves:
98
+ // 1. Register with worker-storage
99
+ // 2. Poll work-queue at interval
100
+ // 3. Claim and process work items
101
+ // 4. Send heartbeats
102
+ // 5. Clean up on shutdown
103
+ console.log('Worker implementation: see @supaku/agentfactory-server for queue operations');
104
+ }
105
+ main().catch((error) => {
106
+ console.error('Fatal error:', error);
107
+ process.exit(1);
108
+ });
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@supaku/agentfactory-cli",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "CLI tools for AgentFactory — local orchestrator, remote worker, queue admin",
6
+ "author": "Supaku (https://supaku.com)",
7
+ "license": "MIT",
8
+ "engines": {
9
+ "node": ">=22.0.0"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/supaku/agentfactory",
14
+ "directory": "packages/cli"
15
+ },
16
+ "homepage": "https://github.com/supaku/agentfactory/tree/main/packages/cli",
17
+ "bugs": {
18
+ "url": "https://github.com/supaku/agentfactory/issues"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "keywords": [
24
+ "cli",
25
+ "orchestrator",
26
+ "worker",
27
+ "agent-management"
28
+ ],
29
+ "bin": {
30
+ "agentfactory": "./dist/src/index.js",
31
+ "af-orchestrator": "./dist/src/orchestrator.js",
32
+ "af-worker": "./dist/src/worker.js"
33
+ },
34
+ "main": "./dist/src/index.js",
35
+ "module": "./dist/src/index.js",
36
+ "types": "./dist/src/index.d.ts",
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/src/index.d.ts",
40
+ "import": "./dist/src/index.js"
41
+ }
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "README.md",
46
+ "LICENSE"
47
+ ],
48
+ "dependencies": {
49
+ "dotenv": "^17.2.3",
50
+ "@supaku/agentfactory": "0.1.0",
51
+ "@supaku/agentfactory-linear": "0.1.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^22.5.4",
55
+ "typescript": "^5.7.3"
56
+ },
57
+ "scripts": {
58
+ "build": "tsc",
59
+ "typecheck": "tsc --noEmit",
60
+ "clean": "rm -rf dist"
61
+ }
62
+ }