@patricio0312rev/agentkit 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/CONTRIBUTING.md +491 -0
- package/LICENSE +21 -0
- package/README.md +442 -0
- package/bin/cli.js +41 -0
- package/package.json +54 -0
- package/src/commands/init.js +312 -0
- package/src/index.js +220 -0
- package/src/lib/config.js +157 -0
- package/src/lib/generator.js +193 -0
- package/src/utils/display.js +95 -0
- package/src/utils/readme.js +191 -0
- package/src/utils/tool-specific.js +408 -0
- package/templates/departments/design/brand-guardian.md +133 -0
- package/templates/departments/design/ui-designer.md +154 -0
- package/templates/departments/design/ux-researcher.md +285 -0
- package/templates/departments/design/visual-storyteller.md +296 -0
- package/templates/departments/design/whimsy-injector.md +318 -0
- package/templates/departments/engineering/ai-engineer.md +386 -0
- package/templates/departments/engineering/backend-architect.md +425 -0
- package/templates/departments/engineering/devops-automator.md +393 -0
- package/templates/departments/engineering/frontend-developer.md +411 -0
- package/templates/departments/engineering/mobile-app-builder.md +412 -0
- package/templates/departments/engineering/rapid-prototyper.md +415 -0
- package/templates/departments/engineering/test-writer-fixer.md +462 -0
- package/templates/departments/marketing/app-store-optimizer.md +176 -0
- package/templates/departments/marketing/content-creator.md +206 -0
- package/templates/departments/marketing/growth-hacker.md +219 -0
- package/templates/departments/marketing/instagram-curator.md +166 -0
- package/templates/departments/marketing/reddit-community-builder.md +192 -0
- package/templates/departments/marketing/tiktok-strategist.md +158 -0
- package/templates/departments/marketing/twitter-engager.md +184 -0
- package/templates/departments/product/feedback-synthesizer.md +143 -0
- package/templates/departments/product/sprint-prioritizer.md +169 -0
- package/templates/departments/product/trend-researcher.md +176 -0
- package/templates/departments/project-management/experiment-tracker.md +128 -0
- package/templates/departments/project-management/project-shipper.md +151 -0
- package/templates/departments/project-management/studio-producer.md +156 -0
- package/templates/departments/studio-operations/analytics-reporter.md +191 -0
- package/templates/departments/studio-operations/finance-tracker.md +242 -0
- package/templates/departments/studio-operations/infrastructure-maintainer.md +202 -0
- package/templates/departments/studio-operations/legal-compliance-checker.md +208 -0
- package/templates/departments/studio-operations/support-responder.md +181 -0
- package/templates/departments/testing/api-tester.md +207 -0
- package/templates/departments/testing/performance-benchmarker.md +262 -0
- package/templates/departments/testing/test-results-analyzer.md +251 -0
- package/templates/departments/testing/tool-evaluator.md +206 -0
- package/templates/departments/testing/workflow-optimizer.md +235 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
const inquirer = require("inquirer");
|
|
2
|
+
const chalk = require("chalk");
|
|
3
|
+
const ora = require("ora");
|
|
4
|
+
const { generateAgents } = require("../lib/generator");
|
|
5
|
+
const { TOOLS, DEPARTMENTS } = require("../lib/config");
|
|
6
|
+
const { displayError, displayBox } = require("../utils/display");
|
|
7
|
+
|
|
8
|
+
async function initCommand(options) {
|
|
9
|
+
console.log(chalk.cyan("\nš Let's set up your AI agents!\n"));
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
let config = {};
|
|
13
|
+
|
|
14
|
+
// Check if all required options provided (non-interactive mode)
|
|
15
|
+
if (options.skipPrompts) {
|
|
16
|
+
if (!options.tool || !options.departments) {
|
|
17
|
+
displayError("--skip-prompts requires --tool and --departments flags");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
config = buildConfigFromFlags(options);
|
|
21
|
+
} else {
|
|
22
|
+
// Interactive mode
|
|
23
|
+
config = await promptUser(options);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Validate configuration
|
|
27
|
+
const validation = validateConfiguration(config);
|
|
28
|
+
if (!validation.isValid) {
|
|
29
|
+
displayError("Configuration validation failed:");
|
|
30
|
+
validation.errors.forEach((err) => console.log(chalk.red(` ⢠${err}`)));
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Generate the configuration
|
|
35
|
+
await generateConfiguration(config);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
displayError(`Failed to initialize: ${error.message}`);
|
|
38
|
+
if (process.env.DEBUG) {
|
|
39
|
+
console.error(error);
|
|
40
|
+
}
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function buildConfigFromFlags(options) {
|
|
46
|
+
return {
|
|
47
|
+
tool: options.tool,
|
|
48
|
+
folder: options.folder || TOOLS[options.tool]?.folder || ".ai",
|
|
49
|
+
departments: options.departments.split(",").map((d) => d.trim()),
|
|
50
|
+
agents: options.agents
|
|
51
|
+
? options.agents.split(",").map((a) => a.trim())
|
|
52
|
+
: [],
|
|
53
|
+
stack: [], // Removed for v0.1.0
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function promptUser(options) {
|
|
58
|
+
const answers = {};
|
|
59
|
+
|
|
60
|
+
// Step 1: Select AI tool
|
|
61
|
+
if (!options.tool) {
|
|
62
|
+
const toolChoices = Object.entries(TOOLS).map(([key, value]) => ({
|
|
63
|
+
name: `${chalk.bold(value.name)} ${chalk.dim("ā")} ${chalk.gray(value.description)}`,
|
|
64
|
+
value: key,
|
|
65
|
+
short: value.name,
|
|
66
|
+
}));
|
|
67
|
+
|
|
68
|
+
const toolAnswer = await inquirer.prompt([
|
|
69
|
+
{
|
|
70
|
+
type: "list",
|
|
71
|
+
name: "tool",
|
|
72
|
+
message: "Which AI tool are you using?",
|
|
73
|
+
choices: toolChoices,
|
|
74
|
+
default: "cursor",
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
77
|
+
answers.tool = toolAnswer.tool;
|
|
78
|
+
} else {
|
|
79
|
+
answers.tool = options.tool;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Step 2: Custom folder name
|
|
83
|
+
const defaultFolder = TOOLS[answers.tool].folder;
|
|
84
|
+
if (!options.folder) {
|
|
85
|
+
const folderAnswer = await inquirer.prompt([
|
|
86
|
+
{
|
|
87
|
+
type: "input",
|
|
88
|
+
name: "folder",
|
|
89
|
+
message: "Folder name for AI agents:",
|
|
90
|
+
default: defaultFolder,
|
|
91
|
+
validate: (input) => {
|
|
92
|
+
if (!input.trim()) return "Folder name cannot be empty";
|
|
93
|
+
if (input.includes(" ")) return "Folder name cannot contain spaces";
|
|
94
|
+
if (input.includes("\\") || input.includes("/"))
|
|
95
|
+
return "Folder name cannot contain path separators";
|
|
96
|
+
return true;
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
]);
|
|
100
|
+
answers.folder = folderAnswer.folder;
|
|
101
|
+
} else {
|
|
102
|
+
answers.folder = options.folder;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Step 3: Select departments
|
|
106
|
+
if (!options.departments) {
|
|
107
|
+
const deptChoices = Object.entries(DEPARTMENTS).map(([key, value]) => ({
|
|
108
|
+
name: `${chalk.bold(value.name)} ${chalk.dim(`(${value.agents.length} agents)`)} ${chalk.gray("ā " + value.description)}`,
|
|
109
|
+
value: key,
|
|
110
|
+
short: value.name,
|
|
111
|
+
checked: ["engineering", "design"].includes(key), // Default selections
|
|
112
|
+
}));
|
|
113
|
+
|
|
114
|
+
const deptAnswer = await inquirer.prompt([
|
|
115
|
+
{
|
|
116
|
+
type: "checkbox",
|
|
117
|
+
name: "departments",
|
|
118
|
+
message: "Select departments to include:",
|
|
119
|
+
choices: deptChoices,
|
|
120
|
+
pageSize: 10,
|
|
121
|
+
validate: (input) => {
|
|
122
|
+
if (input.length === 0)
|
|
123
|
+
return "Please select at least one department";
|
|
124
|
+
return true;
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
]);
|
|
128
|
+
answers.departments = deptAnswer.departments;
|
|
129
|
+
} else {
|
|
130
|
+
answers.departments = options.departments.split(",").map((d) => d.trim());
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Step 4: Select specific agents per department
|
|
134
|
+
answers.agents = [];
|
|
135
|
+
|
|
136
|
+
if (!options.agents) {
|
|
137
|
+
console.log(chalk.cyan("\nš Select agents for each department:\n"));
|
|
138
|
+
|
|
139
|
+
for (const dept of answers.departments) {
|
|
140
|
+
const deptInfo = DEPARTMENTS[dept];
|
|
141
|
+
|
|
142
|
+
const agentChoices = deptInfo.agents.map((agent) => ({
|
|
143
|
+
name: agent,
|
|
144
|
+
value: `${dept}/${agent}`,
|
|
145
|
+
checked: true, // All selected by default
|
|
146
|
+
}));
|
|
147
|
+
|
|
148
|
+
const agentAnswer = await inquirer.prompt([
|
|
149
|
+
{
|
|
150
|
+
type: "checkbox",
|
|
151
|
+
name: "selectedAgents",
|
|
152
|
+
message: `${chalk.bold(deptInfo.name)} agents:`,
|
|
153
|
+
choices: agentChoices,
|
|
154
|
+
pageSize: 15,
|
|
155
|
+
validate: (input) => {
|
|
156
|
+
if (input.length === 0) {
|
|
157
|
+
return `Please select at least one agent from ${deptInfo.name} (or deselect the department)`;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
]);
|
|
163
|
+
|
|
164
|
+
answers.agents.push(...agentAnswer.selectedAgents);
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
answers.agents = options.agents.split(",").map((a) => a.trim());
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Count total agents selected
|
|
171
|
+
const totalAgents = answers.agents.length;
|
|
172
|
+
console.log(
|
|
173
|
+
chalk.dim(`\n ā Total agents selected: ${chalk.bold(totalAgents)}\n`)
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
answers.stack = []; // Removed for v0.1.0
|
|
177
|
+
|
|
178
|
+
return answers;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function validateConfiguration(config) {
|
|
182
|
+
const errors = [];
|
|
183
|
+
|
|
184
|
+
// Validate tool
|
|
185
|
+
if (!config.tool || !TOOLS[config.tool]) {
|
|
186
|
+
errors.push(
|
|
187
|
+
`Invalid tool: ${config.tool}. Valid options: ${Object.keys(TOOLS).join(", ")}`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Validate folder
|
|
192
|
+
if (!config.folder || typeof config.folder !== "string") {
|
|
193
|
+
errors.push("Folder name is required and must be a string");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Validate departments
|
|
197
|
+
if (
|
|
198
|
+
!config.departments ||
|
|
199
|
+
!Array.isArray(config.departments) ||
|
|
200
|
+
config.departments.length === 0
|
|
201
|
+
) {
|
|
202
|
+
errors.push("At least one department is required");
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
config.departments?.forEach((dept) => {
|
|
206
|
+
if (!DEPARTMENTS[dept]) {
|
|
207
|
+
errors.push(
|
|
208
|
+
`Invalid department: ${dept}. Valid options: ${Object.keys(DEPARTMENTS).join(", ")}`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
isValid: errors.length === 0,
|
|
215
|
+
errors,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function generateConfiguration(config) {
|
|
220
|
+
const spinner = ora("Generating AI agent configuration...").start();
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
const result = await generateAgents(config);
|
|
224
|
+
|
|
225
|
+
spinner.succeed(chalk.green("ā Configuration generated successfully!"));
|
|
226
|
+
|
|
227
|
+
// Display results
|
|
228
|
+
displayResults(config, result);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
spinner.fail(chalk.red("Failed to generate configuration"));
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function displayResults(config, result) {
|
|
236
|
+
const tool = TOOLS[config.tool];
|
|
237
|
+
|
|
238
|
+
// Format file location with proper coloring
|
|
239
|
+
const locationLine = `Location: ${chalk.yellow(config.folder + "/")}`;
|
|
240
|
+
const toolLine = `Tool: ${chalk.cyan(tool.name)}`;
|
|
241
|
+
const deptLine = `Departments: ${config.departments.length}`;
|
|
242
|
+
const agentsLine = `Agents: ${result.agentsGenerated || 0}`;
|
|
243
|
+
|
|
244
|
+
displayBox(
|
|
245
|
+
"š Generated Files",
|
|
246
|
+
`${locationLine}\n${toolLine}\n${deptLine}\n${agentsLine}`
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
displayBox("š Usage Instructions", getUsageInstructions(config.tool));
|
|
250
|
+
|
|
251
|
+
const step1 = `1. Review files in ${chalk.yellow(config.folder + "/")}`;
|
|
252
|
+
const step2 = `2. Read ${chalk.yellow(config.folder + "/README.md")}`;
|
|
253
|
+
const step3 = `3. ${getToolSpecificNextStep(config.tool)}`;
|
|
254
|
+
const step4 = `4. Commit to version control to share with team`;
|
|
255
|
+
|
|
256
|
+
displayBox("š Next Steps", `${step1}\n${step2}\n${step3}\n${step4}`);
|
|
257
|
+
|
|
258
|
+
console.log(
|
|
259
|
+
chalk.dim("š” Tip: Run ") +
|
|
260
|
+
chalk.cyan("agentkit init") +
|
|
261
|
+
chalk.dim(" again to regenerate\n")
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function getUsageInstructions(tool) {
|
|
266
|
+
const instructions = {
|
|
267
|
+
"claude-code":
|
|
268
|
+
`With Claude Code CLI:\n` +
|
|
269
|
+
chalk.gray(" $ ") +
|
|
270
|
+
chalk.green('claude-code "Build login page using frontend-developer"\n') +
|
|
271
|
+
`\n` +
|
|
272
|
+
`Agents will be automatically loaded by Claude Code.`,
|
|
273
|
+
|
|
274
|
+
cursor:
|
|
275
|
+
`With Cursor:\n` +
|
|
276
|
+
`1. Use @-mentions in chat:\n` +
|
|
277
|
+
chalk.gray(" @engineering/backend-architect.md ") +
|
|
278
|
+
chalk.dim("Design API\n") +
|
|
279
|
+
`2. Or reference in prompts naturally`,
|
|
280
|
+
|
|
281
|
+
copilot:
|
|
282
|
+
`With GitHub Copilot:\n` +
|
|
283
|
+
`Instructions are in .github/copilot-instructions.md\n` +
|
|
284
|
+
`Copilot will automatically use them.`,
|
|
285
|
+
|
|
286
|
+
aider:
|
|
287
|
+
`With Aider:\n` +
|
|
288
|
+
`Conventions are in .aider/conventions.md\n` +
|
|
289
|
+
`Aider will use them automatically.`,
|
|
290
|
+
|
|
291
|
+
universal:
|
|
292
|
+
`With any AI tool:\n` +
|
|
293
|
+
`Upload relevant agent .md files to your AI chat\n` +
|
|
294
|
+
`and reference them in your prompts.`,
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
return instructions[tool] || instructions.universal;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function getToolSpecificNextStep(tool) {
|
|
301
|
+
const steps = {
|
|
302
|
+
"claude-code": "Start coding: " + chalk.green('claude-code "your task"'),
|
|
303
|
+
cursor: "Open Cursor and use @-mentions",
|
|
304
|
+
copilot: "Start coding - Copilot will use the instructions",
|
|
305
|
+
aider: "Start coding: " + chalk.green("aider --read .aider/"),
|
|
306
|
+
universal: "Open your AI tool and upload the agent files",
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
return steps[tool] || steps.universal;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
module.exports = initCommand;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentKit - Programmatic API
|
|
3
|
+
*
|
|
4
|
+
* This module exports the main functions for use by:
|
|
5
|
+
* - CLI (this package)
|
|
6
|
+
* - VSCode Extension
|
|
7
|
+
* - Other integrations
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { generateAgents } = require('./lib/generator');
|
|
11
|
+
const { TOOLS, DEPARTMENTS, STACKS } = require('./lib/config');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generate AI agent configuration programmatically
|
|
15
|
+
* @param {Object} config - Configuration object
|
|
16
|
+
* @param {string} config.tool - AI tool (claude-code, cursor, copilot, aider, universal)
|
|
17
|
+
* @param {string} config.folder - Target folder name
|
|
18
|
+
* @param {string[]} config.departments - List of departments to include
|
|
19
|
+
* @param {string[]} [config.agents] - Optional: specific agents to include
|
|
20
|
+
* @param {string[]} [config.stack] - Optional: tech stack
|
|
21
|
+
* @param {boolean} [config.skipExamples] - Skip examples in agent files
|
|
22
|
+
* @returns {Promise<Object>} Result object with success status and details
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const agentkit = require('agentkit');
|
|
26
|
+
*
|
|
27
|
+
* const result = await agentkit.generate({
|
|
28
|
+
* tool: 'cursor',
|
|
29
|
+
* folder: '.cursorrules',
|
|
30
|
+
* departments: ['engineering', 'design'],
|
|
31
|
+
* stack: ['react', 'typescript', 'nodejs']
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* console.log(`Generated ${result.agentsGenerated} agents`);
|
|
35
|
+
*/
|
|
36
|
+
async function generate(config) {
|
|
37
|
+
// Validate config
|
|
38
|
+
const validation = validateConfig(config);
|
|
39
|
+
if (!validation.isValid) {
|
|
40
|
+
throw new Error(`Invalid configuration: ${validation.errors.join(', ')}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return await generateAgents(config);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get list of available tools
|
|
48
|
+
* @returns {Object} Tools configuration
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* const tools = agentkit.getTools();
|
|
52
|
+
* console.log(Object.keys(tools)); // ['claude-code', 'cursor', 'copilot', ...]
|
|
53
|
+
*/
|
|
54
|
+
function getTools() {
|
|
55
|
+
return { ...TOOLS };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get list of available departments
|
|
60
|
+
* @returns {Object} Departments configuration
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* const departments = agentkit.getDepartments();
|
|
64
|
+
* console.log(departments.engineering.agents); // ['ai-engineer', 'backend-architect', ...]
|
|
65
|
+
*/
|
|
66
|
+
function getDepartments() {
|
|
67
|
+
return { ...DEPARTMENTS };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get list of available tech stacks
|
|
72
|
+
* @returns {Object} Tech stack configuration
|
|
73
|
+
*/
|
|
74
|
+
function getStacks() {
|
|
75
|
+
return { ...STACKS };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get agents for a specific department
|
|
80
|
+
* @param {string} department - Department name
|
|
81
|
+
* @returns {string[]} List of agent names
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* const agents = agentkit.getAgentsForDepartment('engineering');
|
|
85
|
+
* console.log(agents); // ['ai-engineer', 'backend-architect', ...]
|
|
86
|
+
*/
|
|
87
|
+
function getAgentsForDepartment(department) {
|
|
88
|
+
return DEPARTMENTS[department]?.agents || [];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get all available agents across all departments
|
|
93
|
+
* @returns {Object} Object with department as key and agents array as value
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* const allAgents = agentkit.getAllAgents();
|
|
97
|
+
* console.log(allAgents.engineering); // ['ai-engineer', 'backend-architect', ...]
|
|
98
|
+
*/
|
|
99
|
+
function getAllAgents() {
|
|
100
|
+
const result = {};
|
|
101
|
+
Object.entries(DEPARTMENTS).forEach(([dept, info]) => {
|
|
102
|
+
result[dept] = [...info.agents];
|
|
103
|
+
});
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Validate configuration
|
|
109
|
+
* @param {Object} config - Configuration to validate
|
|
110
|
+
* @returns {Object} Validation result with isValid and errors
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* const validation = agentkit.validateConfig({
|
|
114
|
+
* tool: 'cursor',
|
|
115
|
+
* folder: '.cursorrules',
|
|
116
|
+
* departments: ['engineering']
|
|
117
|
+
* });
|
|
118
|
+
*
|
|
119
|
+
* if (!validation.isValid) {
|
|
120
|
+
* console.error(validation.errors);
|
|
121
|
+
* }
|
|
122
|
+
*/
|
|
123
|
+
function validateConfig(config) {
|
|
124
|
+
const errors = [];
|
|
125
|
+
|
|
126
|
+
// Validate tool
|
|
127
|
+
if (!config.tool) {
|
|
128
|
+
errors.push('Tool is required');
|
|
129
|
+
} else if (!TOOLS[config.tool]) {
|
|
130
|
+
errors.push(`Invalid tool: ${config.tool}. Valid options: ${Object.keys(TOOLS).join(', ')}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Validate folder
|
|
134
|
+
if (!config.folder) {
|
|
135
|
+
errors.push('Folder is required');
|
|
136
|
+
} else if (typeof config.folder !== 'string') {
|
|
137
|
+
errors.push('Folder must be a string');
|
|
138
|
+
} else if (config.folder.includes(' ')) {
|
|
139
|
+
errors.push('Folder name cannot contain spaces');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Validate departments
|
|
143
|
+
if (!config.departments) {
|
|
144
|
+
errors.push('Departments are required');
|
|
145
|
+
} else if (!Array.isArray(config.departments)) {
|
|
146
|
+
errors.push('Departments must be an array');
|
|
147
|
+
} else if (config.departments.length === 0) {
|
|
148
|
+
errors.push('At least one department is required');
|
|
149
|
+
} else {
|
|
150
|
+
config.departments.forEach(dept => {
|
|
151
|
+
if (!DEPARTMENTS[dept]) {
|
|
152
|
+
errors.push(`Invalid department: ${dept}. Valid options: ${Object.keys(DEPARTMENTS).join(', ')}`);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Validate agents if provided
|
|
158
|
+
if (config.agents && !Array.isArray(config.agents)) {
|
|
159
|
+
errors.push('Agents must be an array');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Validate stack if provided
|
|
163
|
+
if (config.stack && !Array.isArray(config.stack)) {
|
|
164
|
+
errors.push('Stack must be an array');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
isValid: errors.length === 0,
|
|
169
|
+
errors
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get recommended configuration based on project type
|
|
175
|
+
* @param {string} projectType - Type of project (web, mobile, fullstack, etc.)
|
|
176
|
+
* @returns {Object} Recommended configuration
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* const config = agentkit.getRecommendedConfig('web');
|
|
180
|
+
* // Returns recommended departments and stack for web projects
|
|
181
|
+
*/
|
|
182
|
+
function getRecommendedConfig(projectType) {
|
|
183
|
+
const recommendations = {
|
|
184
|
+
web: {
|
|
185
|
+
departments: ['engineering', 'design', 'testing'],
|
|
186
|
+
stack: ['react', 'typescript', 'nodejs']
|
|
187
|
+
},
|
|
188
|
+
mobile: {
|
|
189
|
+
departments: ['engineering', 'design', 'testing'],
|
|
190
|
+
stack: ['react-native', 'typescript']
|
|
191
|
+
},
|
|
192
|
+
fullstack: {
|
|
193
|
+
departments: ['engineering', 'design', 'product', 'testing'],
|
|
194
|
+
stack: ['react', 'nodejs', 'postgres', 'typescript']
|
|
195
|
+
},
|
|
196
|
+
startup: {
|
|
197
|
+
departments: ['engineering', 'design', 'product', 'marketing'],
|
|
198
|
+
stack: ['react', 'nodejs', 'postgres']
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
return recommendations[projectType] || recommendations.web;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Export all functions
|
|
206
|
+
module.exports = {
|
|
207
|
+
generate,
|
|
208
|
+
getTools,
|
|
209
|
+
getDepartments,
|
|
210
|
+
getStacks,
|
|
211
|
+
getAgentsForDepartment,
|
|
212
|
+
getAllAgents,
|
|
213
|
+
validateConfig,
|
|
214
|
+
getRecommendedConfig,
|
|
215
|
+
|
|
216
|
+
// Also export config directly for convenience
|
|
217
|
+
TOOLS,
|
|
218
|
+
DEPARTMENTS,
|
|
219
|
+
STACKS
|
|
220
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
const TOOLS = {
|
|
2
|
+
'claude-code': {
|
|
3
|
+
name: 'Claude Code',
|
|
4
|
+
folder: '.claude',
|
|
5
|
+
description: 'Sub-agents with native support',
|
|
6
|
+
fileStructure: 'multi-file',
|
|
7
|
+
supportsSubAgents: true
|
|
8
|
+
},
|
|
9
|
+
'cursor': {
|
|
10
|
+
name: 'Cursor',
|
|
11
|
+
folder: '.cursorrules',
|
|
12
|
+
description: 'Single .cursorrules file or @-mention files',
|
|
13
|
+
fileStructure: 'multi-file',
|
|
14
|
+
supportsSubAgents: true
|
|
15
|
+
},
|
|
16
|
+
'copilot': {
|
|
17
|
+
name: 'GitHub Copilot',
|
|
18
|
+
folder: '.github',
|
|
19
|
+
description: '.github/copilot-instructions.md',
|
|
20
|
+
fileStructure: 'single-file',
|
|
21
|
+
supportsSubAgents: false
|
|
22
|
+
},
|
|
23
|
+
'aider': {
|
|
24
|
+
name: 'Aider',
|
|
25
|
+
folder: '.aider',
|
|
26
|
+
description: 'Aider conventions.md',
|
|
27
|
+
fileStructure: 'single-file',
|
|
28
|
+
supportsSubAgents: false
|
|
29
|
+
},
|
|
30
|
+
'universal': {
|
|
31
|
+
name: 'Universal',
|
|
32
|
+
folder: '.ai',
|
|
33
|
+
description: 'Works with any tool',
|
|
34
|
+
fileStructure: 'multi-file',
|
|
35
|
+
supportsSubAgents: true
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const DEPARTMENTS = {
|
|
40
|
+
design: {
|
|
41
|
+
name: 'Design',
|
|
42
|
+
description: 'Visual design, UX research, and brand management',
|
|
43
|
+
agents: [
|
|
44
|
+
'brand-guardian',
|
|
45
|
+
'ui-designer',
|
|
46
|
+
'ux-researcher',
|
|
47
|
+
'visual-storyteller',
|
|
48
|
+
'whimsy-injector'
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
engineering: {
|
|
52
|
+
name: 'Engineering',
|
|
53
|
+
description: 'Software development, architecture, and DevOps',
|
|
54
|
+
agents: [
|
|
55
|
+
'ai-engineer',
|
|
56
|
+
'backend-architect',
|
|
57
|
+
'devops-automator',
|
|
58
|
+
'frontend-developer',
|
|
59
|
+
'mobile-app-builder',
|
|
60
|
+
'rapid-prototyper',
|
|
61
|
+
'test-writer-fixer'
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
marketing: {
|
|
65
|
+
name: 'Marketing',
|
|
66
|
+
description: 'Growth, content creation, and social media',
|
|
67
|
+
agents: [
|
|
68
|
+
'app-store-optimizer',
|
|
69
|
+
'content-creator',
|
|
70
|
+
'growth-hacker',
|
|
71
|
+
'instagram-curator',
|
|
72
|
+
'reddit-community-builder',
|
|
73
|
+
'tiktok-strategist',
|
|
74
|
+
'twitter-engager'
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
product: {
|
|
78
|
+
name: 'Product',
|
|
79
|
+
description: 'Product management, user feedback, and trends',
|
|
80
|
+
agents: [
|
|
81
|
+
'feedback-synthesizer',
|
|
82
|
+
'sprint-prioritizer',
|
|
83
|
+
'trend-researcher'
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
'project-management': {
|
|
87
|
+
name: 'Project Management',
|
|
88
|
+
description: 'Sprint planning, experiments, and launches',
|
|
89
|
+
agents: [
|
|
90
|
+
'experiment-tracker',
|
|
91
|
+
'project-shipper',
|
|
92
|
+
'studio-producer'
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
'studio-operations': {
|
|
96
|
+
name: 'Studio Operations',
|
|
97
|
+
description: 'Analytics, finance, infrastructure, and support',
|
|
98
|
+
agents: [
|
|
99
|
+
'analytics-reporter',
|
|
100
|
+
'finance-tracker',
|
|
101
|
+
'infrastructure-maintainer',
|
|
102
|
+
'legal-compliance-checker',
|
|
103
|
+
'support-responder'
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
testing: {
|
|
107
|
+
name: 'Testing',
|
|
108
|
+
description: 'Quality assurance, performance, and testing',
|
|
109
|
+
agents: [
|
|
110
|
+
'api-tester',
|
|
111
|
+
'performance-benchmarker',
|
|
112
|
+
'test-results-analyzer',
|
|
113
|
+
'tool-evaluator',
|
|
114
|
+
'workflow-optimizer'
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const STACKS = {
|
|
120
|
+
// Frontend
|
|
121
|
+
react: { name: 'React', category: 'frontend' },
|
|
122
|
+
vue: { name: 'Vue', category: 'frontend' },
|
|
123
|
+
angular: { name: 'Angular', category: 'frontend' },
|
|
124
|
+
svelte: { name: 'Svelte', category: 'frontend' },
|
|
125
|
+
nextjs: { name: 'Next.js', category: 'frontend' },
|
|
126
|
+
|
|
127
|
+
// Backend
|
|
128
|
+
nodejs: { name: 'Node.js', category: 'backend' },
|
|
129
|
+
python: { name: 'Python', category: 'backend' },
|
|
130
|
+
go: { name: 'Go', category: 'backend' },
|
|
131
|
+
rust: { name: 'Rust', category: 'backend' },
|
|
132
|
+
java: { name: 'Java', category: 'backend' },
|
|
133
|
+
|
|
134
|
+
// Database
|
|
135
|
+
postgres: { name: 'PostgreSQL', category: 'database' },
|
|
136
|
+
mongodb: { name: 'MongoDB', category: 'database' },
|
|
137
|
+
mysql: { name: 'MySQL', category: 'database' },
|
|
138
|
+
redis: { name: 'Redis', category: 'database' },
|
|
139
|
+
|
|
140
|
+
// Cloud/Infrastructure
|
|
141
|
+
aws: { name: 'AWS', category: 'cloud' },
|
|
142
|
+
gcp: { name: 'Google Cloud', category: 'cloud' },
|
|
143
|
+
azure: { name: 'Azure', category: 'cloud' },
|
|
144
|
+
vercel: { name: 'Vercel', category: 'cloud' },
|
|
145
|
+
|
|
146
|
+
// Mobile
|
|
147
|
+
'react-native': { name: 'React Native', category: 'mobile' },
|
|
148
|
+
flutter: { name: 'Flutter', category: 'mobile' },
|
|
149
|
+
swift: { name: 'Swift', category: 'mobile' },
|
|
150
|
+
kotlin: { name: 'Kotlin', category: 'mobile' }
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
module.exports = {
|
|
154
|
+
TOOLS,
|
|
155
|
+
DEPARTMENTS,
|
|
156
|
+
STACKS
|
|
157
|
+
};
|