@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.
Files changed (47) hide show
  1. package/CONTRIBUTING.md +491 -0
  2. package/LICENSE +21 -0
  3. package/README.md +442 -0
  4. package/bin/cli.js +41 -0
  5. package/package.json +54 -0
  6. package/src/commands/init.js +312 -0
  7. package/src/index.js +220 -0
  8. package/src/lib/config.js +157 -0
  9. package/src/lib/generator.js +193 -0
  10. package/src/utils/display.js +95 -0
  11. package/src/utils/readme.js +191 -0
  12. package/src/utils/tool-specific.js +408 -0
  13. package/templates/departments/design/brand-guardian.md +133 -0
  14. package/templates/departments/design/ui-designer.md +154 -0
  15. package/templates/departments/design/ux-researcher.md +285 -0
  16. package/templates/departments/design/visual-storyteller.md +296 -0
  17. package/templates/departments/design/whimsy-injector.md +318 -0
  18. package/templates/departments/engineering/ai-engineer.md +386 -0
  19. package/templates/departments/engineering/backend-architect.md +425 -0
  20. package/templates/departments/engineering/devops-automator.md +393 -0
  21. package/templates/departments/engineering/frontend-developer.md +411 -0
  22. package/templates/departments/engineering/mobile-app-builder.md +412 -0
  23. package/templates/departments/engineering/rapid-prototyper.md +415 -0
  24. package/templates/departments/engineering/test-writer-fixer.md +462 -0
  25. package/templates/departments/marketing/app-store-optimizer.md +176 -0
  26. package/templates/departments/marketing/content-creator.md +206 -0
  27. package/templates/departments/marketing/growth-hacker.md +219 -0
  28. package/templates/departments/marketing/instagram-curator.md +166 -0
  29. package/templates/departments/marketing/reddit-community-builder.md +192 -0
  30. package/templates/departments/marketing/tiktok-strategist.md +158 -0
  31. package/templates/departments/marketing/twitter-engager.md +184 -0
  32. package/templates/departments/product/feedback-synthesizer.md +143 -0
  33. package/templates/departments/product/sprint-prioritizer.md +169 -0
  34. package/templates/departments/product/trend-researcher.md +176 -0
  35. package/templates/departments/project-management/experiment-tracker.md +128 -0
  36. package/templates/departments/project-management/project-shipper.md +151 -0
  37. package/templates/departments/project-management/studio-producer.md +156 -0
  38. package/templates/departments/studio-operations/analytics-reporter.md +191 -0
  39. package/templates/departments/studio-operations/finance-tracker.md +242 -0
  40. package/templates/departments/studio-operations/infrastructure-maintainer.md +202 -0
  41. package/templates/departments/studio-operations/legal-compliance-checker.md +208 -0
  42. package/templates/departments/studio-operations/support-responder.md +181 -0
  43. package/templates/departments/testing/api-tester.md +207 -0
  44. package/templates/departments/testing/performance-benchmarker.md +262 -0
  45. package/templates/departments/testing/test-results-analyzer.md +251 -0
  46. package/templates/departments/testing/tool-evaluator.md +206 -0
  47. 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
+ };