agents.dev 1.0.8 → 1.4.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/README.md CHANGED
@@ -1,17 +1,23 @@
1
1
  # agents-dev (Universal Spec CLI)
2
2
 
3
- Ferramenta CLI para configurar automaticamente o ambiente de desenvolvimento e instalar agentes de IA (Auditor, Coder, etc.) para diversas ferramentas como Gemini CLI, Roo Code, Cline e Kilo Code.
3
+ Ferramenta CLI para configurar automaticamente o ambiente de desenvolvimento e instalar agentes de IA (Auditor, Coder, etc.) para diversas ferramentas modernas de IA.
4
4
 
5
5
  ## Funcionalidades
6
6
 
7
7
  ### 1. Instalação de Agentes de IA
8
8
  Lê definições agnósticas (YAML) e converte para formatos específicos:
9
9
  * **Gemini CLI:** Gera arquivos de configuração `.toml`.
10
- * **Roo Code / Cline:** Gera modos customizados (`_custom_modes.json`).
10
+ * **Roo Code / Cline:** Gera modos customizados (`_custom_modes.json`) e regras de contexto em `.roo/` ou `.cline/`.
11
+ * **GitHub Copilot:** Gera instruções em `.github/copilot-instructions.md` e agentes em `.github/agents/`.
12
+ * **Cursor:** Gera regras em `.cursor/rules/*.mdc`.
13
+ * **Windsurf:** Gera regras em `.windsurfrules`.
14
+ * **Trae:** Gera instruções em `.trae/instructions.md`.
15
+ * **OpenCode:** Gera agentes em `.opencode/`.
16
+ * **OpenAI / Claude (Web):** Gera prompts em texto puro na pasta `prompts/`.
11
17
  * **Kilo Code:** Gera prompts em Markdown (`.kilo/prompts/*.md`).
12
18
 
13
- ### 2. Configuração
14
- Automatiza a criação de arquivos de configuração necessários para integrar agentes de IA ao seu fluxo de trabalho.
19
+ ### 2. Configuração de Workflow
20
+ Automatiza a criação da estrutura de documentação (`docs/` e `docs/logs/`) para suportar o fluxo de trabalho dos agentes.
15
21
 
16
22
  ## Instalação e Uso
17
23
 
@@ -20,6 +26,7 @@ Você pode executar a ferramenta diretamente via `npx` sem instalação prévia:
20
26
  ```bash
21
27
  npx agents-dev
22
28
  ```
29
+ *(ou `npx agents.dev`)*
23
30
 
24
31
  Ou instalar globalmente:
25
32
 
@@ -31,8 +38,8 @@ agents-dev
31
38
  ## Como funciona
32
39
 
33
40
  1. Execute `npx agents-dev` na raiz do seu projeto.
34
- 2. A interface interativa perguntará quais configurações você deseja aplicar.
35
- 3. Os arquivos de configuração dos agentes serão gerados na pasta do seu projeto.
41
+ 2. A interface interativa perguntará quais configurações você deseja aplicar e para qual ferramenta.
42
+ 3. Os arquivos de configuração dos agentes serão gerados na pasta do seu projeto automaticamente.
36
43
 
37
44
  ## Estrutura do Projeto
38
45
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents.dev",
3
- "version": "1.0.8",
3
+ "version": "1.4.0",
4
4
  "description": "Instalador automático dos agentes de desenvolvimento",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -1,14 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const fs = require('fs');
4
+ const fsp = require('fs/promises');
4
5
  const path = require('path');
5
- const yaml = require('js-yaml');
6
6
  const { intro, outro, multiselect, select, spinner, note } = require('@clack/prompts');
7
7
  const pc = require('picocolors');
8
8
 
9
9
  // Módulos Internos
10
- const { AgentSchema } = require('./lib/schema');
11
- const { toGeminiTOML, toRooConfig, toKiloMarkdown } = require('./lib/transformers');
10
+ const { loadAgents } = require('./lib/agents');
11
+ const {
12
+ toGeminiTOML,
13
+ toRooConfig,
14
+ toKiloMarkdown,
15
+ toCopilotInstructions,
16
+ toCursorMDC,
17
+ toWindsurfRules,
18
+ toPlainSystemPrompt,
19
+ toTraeRules
20
+ } = require('./lib/transformers');
12
21
  const { generateWorkflowGuide } = require('./lib/docs');
13
22
 
14
23
  async function main() {
@@ -21,7 +30,6 @@ async function main() {
21
30
  options: [
22
31
  { value: 'docs', label: 'Gerar Documentação de Workflow (docs/README.md)', hint: 'Essencial' },
23
32
  { value: 'agents', label: 'Instalar Agentes de IA', hint: 'Recomendado' },
24
- { value: 'vscode', label: 'Configurar VS Code', hint: '(Simulado)' },
25
33
  ],
26
34
  required: true,
27
35
  });
@@ -47,9 +55,15 @@ async function main() {
47
55
  message: 'Onde você deseja instalar os Agentes?',
48
56
  options: [
49
57
  { value: 'gemini', label: 'Gemini CLI', hint: '.gemini/commands/dev' },
50
- { value: 'roo', label: 'Roo Code', hint: 'Gera roo_custom_modes.json' },
51
- { value: 'cline', label: 'Cline', hint: 'Gera cline_custom_modes.json' },
58
+ { value: 'roo', label: 'Roo Code', hint: '.roo/ & custom_modes.json' },
59
+ { value: 'cline', label: 'Cline', hint: '.cline/ & custom_modes.json' },
60
+ { value: 'cursor', label: 'Cursor', hint: '.cursor/rules/*.mdc' },
61
+ { value: 'windsurf', label: 'Windsurf', hint: '.windsurfrules' },
62
+ { value: 'trae', label: 'Trae IDE', hint: '.trae/instructions.md' },
52
63
  { value: 'kilo', label: 'Kilo Code', hint: '.kilo/prompts/*.md' },
64
+ { value: 'copilot', label: 'GitHub Copilot', hint: '.github/copilot-instructions.md' },
65
+ { value: 'web', label: 'OpenAI / Claude', hint: 'prompts/*.txt (Copiar & Colar)' },
66
+ { value: 'opencode', label: 'OpenCode', hint: '.opencode/*.md' },
53
67
  ],
54
68
  });
55
69
 
@@ -65,69 +79,121 @@ async function processAgentsInstallation(tool) {
65
79
  const s = spinner();
66
80
  s.start('Carregando definições...');
67
81
 
68
- const definitionsDir = path.join(__dirname, '..', 'definitions');
69
- if (!fs.existsSync(definitionsDir)) {
70
- s.stop('Falha');
71
- note(`Pasta de definições não encontrada: ${definitionsDir}`, 'Erro Fatal');
72
- return;
73
- }
74
-
75
- const files = fs.readdirSync(definitionsDir).filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
76
- const validAgents = [];
82
+ try {
83
+ const validAgents = await loadAgents();
77
84
 
78
- // Validação e Carregamento
79
- for (const file of files) {
80
- try {
81
- const content = fs.readFileSync(path.join(definitionsDir, file), 'utf8');
82
- const raw = yaml.load(content);
83
-
84
- // Validação com Zod
85
- const parsed = AgentSchema.safeParse(raw);
86
- if (!parsed.success) {
87
- console.warn(pc.yellow(`⚠️ Ignorando ${file}: Inválido`));
88
- continue;
89
- }
90
-
91
- const agent = parsed.data;
92
- agent.slug = file.replace(/\.ya?ml$/, '').replace(/\./g, '-'); // dev.coder -> dev-coder
93
- validAgents.push(agent);
94
-
95
- } catch (e) {
96
- console.error(pc.red(`Erro ao ler ${file}: ${e.message}`));
85
+ if (validAgents.length === 0) {
86
+ s.stop('Nenhum agente válido encontrado.');
87
+ return;
97
88
  }
98
- }
99
89
 
100
- s.message(`Instalando ${validAgents.length} agentes para ${tool}...`);
90
+ s.message(`Instalando ${validAgents.length} agentes para ${tool}...`);
101
91
 
102
- // Instalação Específica por Ferramenta
103
- try {
92
+ // Instalação Específica por Ferramenta
104
93
  if (tool === 'gemini') {
105
94
  const targetDir = path.join(process.cwd(), '.gemini', 'commands', 'dev');
106
- if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true });
95
+ await fsp.mkdir(targetDir, { recursive: true });
107
96
 
108
- for (const agent of validAgents) {
97
+ await Promise.all(validAgents.map(agent => {
109
98
  const toml = toGeminiTOML(agent);
110
- // Nome original com pontos (dev.coder.toml) é preferível para Gemini CLI
111
- const fileName = `${agent.slug.replace(/-/g, '.')}.toml`;
112
- fs.writeFileSync(path.join(targetDir, fileName), toml);
113
- }
99
+ // Usa originalName para manter pontos (dev.coder.toml)
100
+ const fileName = `${agent.originalName}.toml`;
101
+ return fsp.writeFile(path.join(targetDir, fileName), toml);
102
+ }));
114
103
  }
115
104
  else if (tool === 'roo' || tool === 'cline') {
105
+ const configDir = tool === 'roo' ? '.roo' : '.cline';
106
+ const targetDir = path.join(process.cwd(), configDir);
107
+ await fsp.mkdir(targetDir, { recursive: true });
108
+
109
+ // 1. Gera arquivos Markdown (Contexto)
110
+ await Promise.all(validAgents.map(agent => {
111
+ const md = toKiloMarkdown(agent); // Reutiliza formato Markdown padrão
112
+ return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
113
+ }));
114
+
115
+ // 2. Gera JSON para Custom Modes (Configuração da Extensão)
116
116
  const modes = validAgents.map(agent => toRooConfig(agent, agent.slug));
117
117
  const jsonContent = JSON.stringify({ customModes: modes }, null, 2);
118
118
  const fileName = `${tool}_custom_modes.json`;
119
- fs.writeFileSync(path.join(process.cwd(), fileName), jsonContent);
120
- note(`Copie o conteúdo de '${fileName}' para as configurações da extensão.`, 'Ação Manual');
119
+ await fsp.writeFile(path.join(process.cwd(), fileName), jsonContent);
120
+
121
+ note(`1. Arquivos de contexto salvos em '${configDir}/'\n2. Copie o conteúdo de '${fileName}' para configurar os modos na extensão.`, 'Configuração Híbrida');
121
122
  }
122
123
  else if (tool === 'kilo') {
123
124
  const targetDir = path.join(process.cwd(), '.kilo', 'prompts');
124
- if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true });
125
+ await fsp.mkdir(targetDir, { recursive: true });
125
126
 
126
- for (const agent of validAgents) {
127
+ await Promise.all(validAgents.map(agent => {
127
128
  const md = toKiloMarkdown(agent);
128
- fs.writeFileSync(path.join(targetDir, `${agent.slug}.md`), md);
129
- }
129
+ return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
130
+ }));
131
+ }
132
+ else if (tool === 'copilot') {
133
+ const githubDir = path.join(process.cwd(), '.github');
134
+ const agentsDir = path.join(githubDir, 'agents');
135
+ await fsp.mkdir(agentsDir, { recursive: true });
136
+
137
+ // 1. Gera todos os agentes individuais
138
+ await Promise.all(validAgents.map(agent => {
139
+ const md = toCopilotInstructions(agent);
140
+ return fsp.writeFile(path.join(agentsDir, `${agent.slug}.md`), md);
141
+ }));
142
+
143
+ // 2. Define o copilot-instructions.md principal
144
+ // Tenta achar o 'dev.coder' ou usa o primeiro da lista
145
+ const mainAgent = validAgents.find(a => a.slug.includes('coder')) || validAgents[0];
146
+ const mainInstructions = toCopilotInstructions(mainAgent);
147
+
148
+ await fsp.writeFile(path.join(githubDir, 'copilot-instructions.md'), mainInstructions);
149
+ note(`Agente principal (${mainAgent.name}) definido em .github/copilot-instructions.md\nOutros agentes salvos em .github/agents/`, 'Configuração Copilot');
150
+ }
151
+ else if (tool === 'cursor') {
152
+ const rulesDir = path.join(process.cwd(), '.cursor', 'rules');
153
+ await fsp.mkdir(rulesDir, { recursive: true });
154
+
155
+ await Promise.all(validAgents.map(agent => {
156
+ const mdc = toCursorMDC(agent);
157
+ return fsp.writeFile(path.join(rulesDir, `${agent.slug}.mdc`), mdc);
158
+ }));
159
+ note(`Regras salvas em .cursor/rules/*.mdc`, 'Configuração Cursor');
160
+ }
161
+ else if (tool === 'windsurf') {
162
+ const mainAgent = validAgents.find(a => a.slug.includes('coder')) || validAgents[0];
163
+ const rules = toWindsurfRules(mainAgent);
164
+ await fsp.writeFile(path.join(process.cwd(), '.windsurfrules'), rules);
165
+ note(`Regras salvas em .windsurfrules usando o perfil do agente ${mainAgent.name}`, 'Configuração Windsurf');
166
+ }
167
+ else if (tool === 'trae') {
168
+ const traeDir = path.join(process.cwd(), '.trae');
169
+ await fsp.mkdir(traeDir, { recursive: true });
170
+
171
+ const mainAgent = validAgents.find(a => a.slug.includes('coder')) || validAgents[0];
172
+ const rules = toTraeRules(mainAgent);
173
+ await fsp.writeFile(path.join(traeDir, 'instructions.md'), rules);
174
+ note(`Instruções salvas em .trae/instructions.md`, 'Configuração Trae');
175
+ }
176
+ else if (tool === 'web') {
177
+ const targetDir = path.join(process.cwd(), 'prompts');
178
+ await fsp.mkdir(targetDir, { recursive: true });
179
+
180
+ await Promise.all(validAgents.map(agent => {
181
+ const txt = toPlainSystemPrompt(agent);
182
+ return fsp.writeFile(path.join(targetDir, `${agent.slug}.txt`), txt);
183
+ }));
184
+ note(`Prompts salvos na pasta 'prompts/'. Copie e cole no ChatGPT ou Claude.`, 'Configuração Web');
185
+ }
186
+ else if (tool === 'opencode') {
187
+ const targetDir = path.join(process.cwd(), '.opencode');
188
+ await fsp.mkdir(targetDir, { recursive: true });
189
+
190
+ await Promise.all(validAgents.map(agent => {
191
+ const md = toKiloMarkdown(agent); // Reutiliza Markdown padrão
192
+ return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
193
+ }));
194
+ note(`Agentes salvos em .opencode/*.md`, 'Configuração OpenCode');
130
195
  }
196
+
131
197
  s.stop('Instalação finalizada!');
132
198
 
133
199
  } catch (e) {
@@ -0,0 +1,68 @@
1
+ const fs = require('fs/promises');
2
+ const path = require('path');
3
+ const yaml = require('js-yaml');
4
+ const { AgentSchema } = require('./schema');
5
+ const pc = require('picocolors');
6
+
7
+ /**
8
+ * Carrega e valida todas as definições de agentes da pasta definitions
9
+ * @returns {Promise<Array>} Lista de agentes validados
10
+ */
11
+ async function loadAgents() {
12
+ const definitionsDir = path.join(__dirname, '..', '..', 'definitions');
13
+
14
+ try {
15
+ await fs.access(definitionsDir);
16
+ } catch {
17
+ throw new Error(`Pasta de definições não encontrada: ${definitionsDir}`);
18
+ }
19
+
20
+ const files = await fs.readdir(definitionsDir);
21
+ const yamlFiles = files.filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
22
+
23
+ // Leitura e processamento em paralelo
24
+ const results = await Promise.all(yamlFiles.map(async (file) => {
25
+ try {
26
+ const content = await fs.readFile(path.join(definitionsDir, file), 'utf8');
27
+ const raw = yaml.load(content);
28
+
29
+ const parsed = AgentSchema.safeParse(raw);
30
+ if (!parsed.success) {
31
+ return {
32
+ success: false,
33
+ file,
34
+ error: 'Validação do Schema falhou',
35
+ details: parsed.error.format()
36
+ };
37
+ }
38
+
39
+ const agent = parsed.data;
40
+ // Normaliza o slug: dev.coder -> dev-coder
41
+ agent.slug = file.replace(/\.ya?ml$/, '').replace(/\./g, '-');
42
+ // Mantém o nome original do arquivo para referência (útil para Gemini CLI)
43
+ agent.originalName = file.replace(/\.ya?ml$/, '');
44
+
45
+ return { success: true, agent };
46
+
47
+ } catch (e) {
48
+ return { success: false, file, error: e.message };
49
+ }
50
+ }));
51
+
52
+ // Separa sucessos e falhas
53
+ const validAgents = [];
54
+ const errors = [];
55
+
56
+ results.forEach(res => {
57
+ if (res.success) {
58
+ validAgents.push(res.agent);
59
+ } else {
60
+ errors.push(res);
61
+ console.warn(pc.yellow(`⚠️ Ignorando ${res.file}: ${res.error}`));
62
+ }
63
+ });
64
+
65
+ return validAgents;
66
+ }
67
+
68
+ module.exports = { loadAgents };
package/src/lib/docs.js CHANGED
@@ -3,12 +3,18 @@ const path = require('path');
3
3
  const pc = require('picocolors');
4
4
 
5
5
  /**
6
- * Gera o guia de workflow do projeto
6
+ * Gera o guia de workflow e a estrutura de pastas necessária para os agentes
7
7
  */
8
8
  function generateWorkflowGuide(baseDir) {
9
9
  const docsDir = path.join(baseDir, 'docs');
10
+ const logsDir = path.join(docsDir, 'logs');
10
11
 
11
- // Conteúdo baseado no exemplo provided
12
+ // Cria a estrutura de pastas recursivamente (Funciona em Windows, Mac e Linux)
13
+ if (!fs.existsSync(logsDir)) {
14
+ fs.mkdirSync(logsDir, { recursive: true });
15
+ }
16
+
17
+ // Conteúdo do README.md
12
18
  const content = `# 🤖 Agent Workflow Guide
13
19
 
14
20
  Este documento descreve o fluxo de desenvolvimento padrão usando os Agentes instalados.
@@ -86,12 +92,13 @@ O sistema segue um processo **Waterfall** para planejamento (precisão) e **Iter
86
92
  \`changelog.md\`
87
93
  `;
88
94
 
89
- if (!fs.existsSync(docsDir)) {
90
- fs.mkdirSync(docsDir, { recursive: true });
91
- fs.writeFileSync(path.join(docsDir, 'README.md'), content);
95
+ const readmePath = path.join(docsDir, 'README.md');
96
+ if (!fs.existsSync(readmePath)) {
97
+ fs.writeFileSync(readmePath, content);
92
98
  return true;
93
99
  }
94
- return false;
100
+
101
+ return true; // Retorna true indicando que a estrutura foi garantida
95
102
  }
96
103
 
97
104
  module.exports = { generateWorkflowGuide };
@@ -86,4 +86,114 @@ function toKiloMarkdown(agent) {
86
86
  return parts.join('\n');
87
87
  }
88
88
 
89
- module.exports = { toGeminiTOML, toRooConfig, toKiloMarkdown };
89
+ /**
90
+ * Converte para Instruções do GitHub Copilot (.github/copilot-instructions.md)
91
+ */
92
+ function toCopilotInstructions(agent) {
93
+ const parts = [
94
+ `<!-- GitHub Copilot Instructions for ${agent.name} -->`,
95
+ `# Identity and Role`,
96
+ `You are **${agent.name}** ${agent.emoji}.`,
97
+ `**Role**: ${agent.role}`,
98
+ `\n## Core Instructions`,
99
+ agent.systemPrompt.trim(),
100
+ '\n'
101
+ ];
102
+
103
+ if (agent.rules && agent.rules.length > 0) {
104
+ parts.push(`## Rules & Guidelines`);
105
+ agent.rules.forEach(rule => parts.push(`- ${rule}`));
106
+ }
107
+
108
+ // Adiciona uma seção de estilo de resposta para garantir conformidade
109
+ parts.push(`\n## Response Style`);
110
+ parts.push(`- Be concise and objective.`);
111
+ parts.push(`- Use Portuguese (Brazil) unless told otherwise.`);
112
+ parts.push(`- Follow the project conventions defined in the workspace.`);
113
+
114
+ return parts.join('\n');
115
+ }
116
+
117
+ /**
118
+ * Converte para Cursor Rules (.mdc)
119
+ * Inclui Frontmatter para Contexto
120
+ */
121
+ function toCursorMDC(agent) {
122
+ // Tenta inferir globs baseados no papel do agente
123
+ let globs = "*";
124
+ const roleLower = agent.slug.toLowerCase();
125
+
126
+ if (roleLower.includes('test') || roleLower.includes('qa')) globs = "*.test.*, *.spec.*, **/tests/**";
127
+ if (roleLower.includes('css') || roleLower.includes('style')) globs = "*.css, *.scss, *.tailwind";
128
+ if (roleLower.includes('sql') || roleLower.includes('db')) globs = "*.sql, *.prisma, *.schema";
129
+
130
+ return `---
131
+ description: ${agent.description || agent.role}
132
+ globs: ${globs}
133
+ ---
134
+ # ${agent.name} ${agent.emoji}
135
+
136
+ Role: ${agent.role}
137
+
138
+ ## Instructions
139
+ ${agent.systemPrompt.trim()}
140
+
141
+ ${agent.rules && agent.rules.length > 0 ? '## Rules\n' + agent.rules.map(r => `- ${r}`).join('\n') : ''}
142
+ `;
143
+ }
144
+
145
+ /**
146
+ * Converte para Windsurf (.windsurfrules)
147
+ */
148
+ function toWindsurfRules(agent) {
149
+ return `# ${agent.name} ${agent.emoji} Rules
150
+
151
+ Role: ${agent.role}
152
+
153
+ ## Core Logic
154
+ ${agent.systemPrompt.trim()}
155
+
156
+ ${agent.rules && agent.rules.length > 0 ? '## Guidelines\n' + agent.rules.map(r => `- ${r}`).join('\n') : ''}
157
+ `;
158
+ }
159
+
160
+ /**
161
+ * Converte para System Prompt Puro (OpenAI/Claude/Web)
162
+ */
163
+ function toPlainSystemPrompt(agent) {
164
+ return `You are ${agent.name} ${agent.emoji}
165
+ Role: ${agent.role}
166
+
167
+ [SYSTEM INSTRUCTIONS]
168
+ ${agent.systemPrompt.trim()}
169
+
170
+ ${agent.rules && agent.rules.length > 0 ? '[GUIDELINES]\n' + agent.rules.map(r => `- ${r}`).join('\n') : ''}
171
+ `;
172
+ }
173
+
174
+ /**
175
+ * Converte para Trae Instructions
176
+ */
177
+ function toTraeRules(agent) {
178
+ return `<!-- Trae Workspace Rules -->
179
+ # ${agent.name} ${agent.emoji}
180
+
181
+ **Role**: ${agent.role}
182
+
183
+ ## Context & Instructions
184
+ ${agent.systemPrompt.trim()}
185
+
186
+ ${agent.rules && agent.rules.length > 0 ? '## Constraints\n' + agent.rules.map(r => `- ${r}`).join('\n') : ''}
187
+ `;
188
+ }
189
+
190
+ module.exports = {
191
+ toGeminiTOML,
192
+ toRooConfig,
193
+ toKiloMarkdown,
194
+ toCopilotInstructions,
195
+ toCursorMDC,
196
+ toWindsurfRules,
197
+ toPlainSystemPrompt,
198
+ toTraeRules
199
+ };