sdd-toolkit 1.9.1 → 2.0.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.
@@ -1,332 +1,322 @@
1
- const { TRANSLATIONS } = require('./messages');
2
-
3
- /**
4
- * Returns the language rule based on the locale
5
- * @param {string} locale - 'en', 'pt-br', 'es', etc.
6
- */
7
- function getLanguageRule(locale = 'en') {
8
- const normalized = locale.toLowerCase().replace('-', '_');
9
-
10
- // Mapping locale slug to property key in messages
11
- const keyMap = {
12
- 'en': 'EN',
13
- 'pt_br': 'PT_BR',
14
- 'es': 'ES'
15
- };
16
-
17
- const ruleKey = keyMap[normalized] || 'EN';
18
-
19
- // Get dictionary for the target locale or fallback to EN
20
- const dict = TRANSLATIONS[normalized] || TRANSLATIONS['en'];
21
-
22
- return dict.LANGUAGE_RULES[ruleKey];
23
- }
24
-
25
- /**
26
- * Converte definição do agente para TOML do Gemini CLI
27
- */
28
- function toGeminiTOML(agent, options = {}) {
29
- const languageRule = getLanguageRule(options.locale);
30
- // Escapa aspas duplas na descrição
31
- const description = (agent.description || agent.role).replace(/"/g, '\"');
32
-
33
- // Constrói o prompt completo
34
- const parts = [
35
- `# Identity`,
36
- `You are **${agent.name}** ${agent.emoji}`,
37
- `Role: ${agent.role}\n`,
38
- `# Core Instructions`,
39
- agent.systemPrompt.trim(),
40
- '\n'
41
- ];
42
-
43
- const allRules = [languageRule, ...(agent.rules || [])];
44
-
45
- if (allRules.length > 0) {
46
- parts.push(`# Rules & Guidelines`);
47
- allRules.forEach(rule => parts.push(`- ${rule}`));
48
- parts.push('\n');
49
- }
50
-
51
- const fullPrompt = parts.join('\n');
52
-
53
- // Escapa aspas triplas para o bloco multilinha TOML
54
- const escapedPrompt = fullPrompt.replace(/"""/g, '\"\"\"');
55
-
56
- // Monta o TOML final
57
- let toml = `description = "${description}"\n`;
58
- toml += `prompt = """\n${escapedPrompt}\n"""\n`;
59
-
60
- // Mantém rules como array separado se a ferramenta suportar (Gemini CLI suporta)
61
- if (allRules.length > 0) {
62
- toml += 'rules = [\n';
63
- allRules.forEach(rule => {
64
- const escaped = rule.replace(/\\/g, '\\\\').replace(/"/g, '\"');
65
- toml += ` "${escaped}",\n`;
66
- });
67
- toml += ']\n';
68
- }
69
-
70
- return toml;
71
- }
72
-
73
- /**
74
- * Converte para configuração de Custom Mode do Roo Code / Cline (JSON)
75
- */
76
- function toRooConfig(agent, slug, options = {}) {
77
- const languageRule = getLanguageRule(options.locale);
78
- const promptParts = [
79
- `# ${agent.name} (${agent.role})`,
80
- `\n${agent.systemPrompt.trim()}\n`
81
- ];
82
-
83
- const allRules = [languageRule, ...(agent.rules || [])];
84
-
85
- if (allRules.length > 0) {
86
- promptParts.push(`## Rules & Guidelines`);
87
- allRules.forEach(rule => promptParts.push(`- ${rule}`));
88
- }
89
-
90
- return {
91
- slug: slug,
92
- name: `${agent.emoji} ${agent.name}`,
93
- roleDefinition: promptParts.join('\n'),
94
- groups: ["read", "edit", "browser", "command", "mcp"]
95
- };
96
- }
97
-
98
- /**
99
- * Converte para Markdown do Kilo Code
100
- */
101
- function toKiloMarkdown(agent, options = {}) {
102
- const languageRule = getLanguageRule(options.locale);
103
- const parts = [
104
- `<!--- Kilo Code Agent Config --->`,
105
- `# ${agent.name} ${agent.emoji}`,
106
- `**Role**: ${agent.role}\n`,
107
- `## Instructions`,
108
- agent.systemPrompt.trim(),
109
- '\n'
110
- ];
111
-
112
- const allRules = [languageRule, ...(agent.rules || [])];
113
-
114
- if (allRules.length > 0) {
115
- parts.push(`## Constraints`);
116
- allRules.forEach(rule => parts.push(`- ${rule}`));
117
- }
118
-
119
- return parts.join('\n');
120
- }
121
-
122
- /**
123
- * Converte para Instruções do GitHub Copilot (.github/copilot-instructions.md)
124
- */
125
- function toCopilotInstructions(agent, options = {}) {
126
- const languageRule = getLanguageRule(options.locale);
127
- const parts = [
128
- `<!-- GitHub Copilot Instructions for ${agent.name} -->`,
129
- `# Identity and Role`,
130
- `You are **${agent.name}** ${agent.emoji}.`,
131
- `**Role**: ${agent.role}`,
132
- `\n## Core Instructions`,
133
- agent.systemPrompt.trim(),
134
- '\n'
135
- ];
136
-
137
- const allRules = [languageRule, ...(agent.rules || [])];
138
-
139
- if (allRules.length > 0) {
140
- parts.push(`## Rules & Guidelines`);
141
- allRules.forEach(rule => parts.push(`- ${rule}`));
142
- }
143
-
144
- // Adiciona uma seção de estilo de resposta para garantir conformidade
145
- parts.push(`\n## Response Style`);
146
- parts.push(`- Be concise and objective.`);
147
- parts.push(`- Follow the project conventions defined in the workspace.`);
148
-
149
- return parts.join('\n');
150
- }
151
-
152
- /**
153
- * Converte para Cursor Rules (.mdc)
154
- * Inclui Frontmatter para Contexto
155
- */
156
- function toCursorMDC(agent, options = {}) {
157
- const languageRule = getLanguageRule(options.locale);
158
- // Tenta inferir globs baseados no papel do agente
159
- let globs = "*";
160
- const roleLower = agent.slug.toLowerCase();
161
-
162
- if (roleLower.includes('test') || roleLower.includes('qa')) globs = "*.test.*, *.spec.*, **/tests/**";
163
- if (roleLower.includes('css') || roleLower.includes('style')) globs = "*.css, *.scss, *.tailwind";
164
- if (roleLower.includes('sql') || roleLower.includes('db')) globs = "*.sql, *.prisma, *.schema";
165
-
166
- const allRules = [languageRule, ...(agent.rules || [])];
167
-
168
- return `---
169
- description: ${agent.description || agent.role}
170
- globs: ${globs}
171
- ---
172
- # ${agent.name} ${agent.emoji}
173
-
174
- Role: ${agent.role}
175
-
176
- ## Instructions
177
- ${agent.systemPrompt.trim()}
178
-
179
- ${allRules.length > 0 ? '## Rules\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
180
- `;
181
- }
182
-
183
- /**
184
- * Converte para Windsurf Workflow (.windsurf/workflows/*.md)
185
- * Cascade reconhece esses arquivos como comandos de workflow
186
- */
187
- function toWindsurfRules(agent, options = {}) {
188
- const languageRule = getLanguageRule(options.locale);
189
- const allRules = [languageRule, ...(agent.rules || [])];
190
-
191
- return `# ${agent.name} ${agent.emoji} Rules
192
-
193
- Role: ${agent.role}
194
-
195
- ## Core Logic
196
- ${agent.systemPrompt.trim()}
197
-
198
- ${allRules.length > 0 ? '## Guidelines\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
199
- `;
200
- }
201
-
202
- /**
203
- * Converte para Claude Code Command (.claude/commands/agents/*.md)
204
- */
205
- function toClaudeCommand(agent, options = {}) {
206
- const languageRule = getLanguageRule(options.locale);
207
- const allRules = [languageRule, ...(agent.rules || [])];
208
-
209
- return `---
210
- name: Agent: ${agent.name}
211
- description: ${agent.description || agent.role}
212
- category: Agents
213
- ---
214
- # ${agent.name} ${agent.emoji}
215
-
216
- Role: ${agent.role}
217
-
218
- ## Instructions
219
- ${agent.systemPrompt.trim()}
220
-
221
- ${allRules.length > 0 ? '## Rules\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
222
- `;
223
- }
224
-
225
- /**
226
- * Converte para System Prompt Puro (OpenAI/Claude/Web)
227
- */
228
- function toPlainSystemPrompt(agent, options = {}) {
229
- const languageRule = getLanguageRule(options.locale);
230
- const allRules = [languageRule, ...(agent.rules || [])];
231
-
232
- return `You are ${agent.name} ${agent.emoji}
233
- Role: ${agent.role}
234
-
235
- [SYSTEM INSTRUCTIONS]
236
- ${agent.systemPrompt.trim()}
237
-
238
- ${allRules.length > 0 ? '[GUIDELINES]\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
239
- `;
240
- }
241
-
242
- /**
243
- * Converte para Trae Instructions
244
- */
245
- function toTraeRules(agent, options = {}) {
246
- const languageRule = getLanguageRule(options.locale);
247
- const allRules = [languageRule, ...(agent.rules || [])];
248
-
249
- return `<!-- Trae Workspace Rules -->
250
- # ${agent.name} ${agent.emoji}
251
-
252
- **Role**: ${agent.role}
253
-
254
- ## Context & Instructions
255
- ${agent.systemPrompt.trim()}
256
-
257
- ${allRules.length > 0 ? '## Constraints\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
258
- `;
259
- }
260
-
261
- /**
262
- * Converte para OpenCode Agent (.opencode/agent/*.md)
263
- */
264
- function toOpenCodeAgent(agent, options = {}) {
265
- const languageRule = getLanguageRule(options.locale);
266
- const allRules = [languageRule, ...(agent.rules || [])];
267
-
268
- // Configurar permissões baseado no tipo de agente
269
- const isReadOnly = agent.slug.includes('review') || agent.slug.includes('audit') || agent.name.includes('Architect') || agent.role.includes('QA') || agent.role.includes('Review');
270
- const tools = {
271
- write: !isReadOnly,
272
- edit: !isReadOnly,
273
- bash: !isReadOnly
274
- };
275
-
276
- const frontmatter = {
277
- description: agent.description || agent.role,
278
- mode: 'subagent',
279
- temperature: 0.3,
280
- tools
281
- };
282
-
283
- const frontmatterStr = Object.entries(frontmatter)
284
- .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
285
- .join('\n');
286
-
287
- return `---
288
- ${frontmatterStr}
289
- ---
290
-
291
- # ${agent.name} ${agent.emoji}
292
-
293
- **Role**: ${agent.role}
294
-
295
- ${agent.systemPrompt.trim()}
296
-
297
- ## Rules
298
- ${allRules.map(rule => `- ${rule}`).join('\n')}
299
- `;
300
- }
301
-
302
- /**
303
- * Converte para Trae Instructions
304
- */
305
- function toTraeRules(agent, options = {}) {
306
- const languageRule = getLanguageRule(options.locale);
307
- const allRules = [languageRule, ...(agent.rules || [])];
308
-
309
- return `<!-- Trae Workspace Rules -->
310
- # ${agent.name} ${agent.emoji}
311
-
312
- **Role**: ${agent.role}
313
-
314
- ## Context & Instructions
315
- ${agent.systemPrompt.trim()}
316
-
317
- ${allRules.length > 0 ? '## Constraints\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
318
- `;
319
- }
320
-
321
- module.exports = {
322
- toGeminiTOML,
323
- toRooConfig,
324
- toKiloMarkdown,
325
- toCopilotInstructions,
326
- toCursorMDC,
327
- toWindsurfRules,
328
- toClaudeCommand,
329
- toPlainSystemPrompt,
330
- toTraeRules,
331
- toOpenCodeAgent
332
- };
1
+ const { TRANSLATIONS } = require('./messages');
2
+
3
+ /**
4
+ * Returns the language rule based on the locale
5
+ * @param {string} locale - 'en', 'pt-br', 'es', etc.
6
+ */
7
+ function getLanguageRule(locale = 'en') {
8
+ const normalized = locale.toLowerCase().replace('-', '_');
9
+
10
+ // Mapping locale slug to property key in messages
11
+ const keyMap = {
12
+ 'en': 'EN',
13
+ 'pt_br': 'PT_BR',
14
+ 'es': 'ES'
15
+ };
16
+
17
+ const ruleKey = keyMap[normalized] || 'EN';
18
+
19
+ // Get dictionary for the target locale or fallback to EN
20
+ const dict = TRANSLATIONS[normalized] || TRANSLATIONS['en'];
21
+
22
+ return dict.LANGUAGE_RULES[ruleKey];
23
+ }
24
+
25
+ /**
26
+ */
27
+ function toGeminiTOML(agent, options = {}) {
28
+ const languageRule = getLanguageRule(options.locale);
29
+ // Escapa aspas duplas na descrição
30
+ const description = (agent.description || agent.role).replace(/"/g, '\"');
31
+
32
+ // Constrói o prompt completo
33
+ const parts = [
34
+ `# Identity`,
35
+ `You are **${agent.name}** ${agent.emoji}`,
36
+ `Role: ${agent.role}\n`,
37
+ `# Core Instructions`,
38
+ agent.systemPrompt.trim(),
39
+ '\n'
40
+ ];
41
+
42
+ const allRules = [languageRule, ...(agent.rules || [])];
43
+
44
+ if (allRules.length > 0) {
45
+ parts.push(`# Rules & Guidelines`);
46
+ allRules.forEach(rule => parts.push(`- ${rule}`));
47
+ parts.push('\n');
48
+ }
49
+
50
+ const fullPrompt = parts.join('\n');
51
+ const escapedPrompt = fullPrompt.replace(/"""/g, '\"\"\"');
52
+
53
+ // Monta o TOML final
54
+ let toml = `description = "${description}"\n`;
55
+ toml += `prompt = """\n${escapedPrompt}\n"""\n`;
56
+
57
+ if (allRules.length > 0) {
58
+ toml += 'rules = [\n';
59
+ allRules.forEach(rule => {
60
+ const escaped = rule.replace(/\\/g, '\\\\').replace(/"/g, '\"');
61
+ toml += ` "${escaped}",\n`;
62
+ });
63
+ toml += ']\n';
64
+ }
65
+
66
+ return toml;
67
+ }
68
+
69
+ /**
70
+ * Converte para configuração de Custom Mode do Roo Code / Cline (JSON)
71
+ */
72
+ function toRooConfig(agent, slug, options = {}) {
73
+ const languageRule = getLanguageRule(options.locale);
74
+ const parts = [
75
+ `# ${agent.name} (${agent.role})`,
76
+ `\n${agent.systemPrompt.trim()}\n`
77
+ ];
78
+
79
+ const allRules = [languageRule, ...(agent.rules || [])];
80
+
81
+ parts.push(`## Rules & Guidelines`);
82
+ }
83
+
84
+ return {
85
+ slug: slug,
86
+ roleDefinition: parts.join('\n'),
87
+ groups: ["read", "edit", "browser", "command", "mcp"]
88
+ };
89
+ }
90
+
91
+ /**
92
+ * Converte para Markdown do Kilo Code
93
+ function toKiloMarkdown(agent, options = {}) {
94
+ const languageRule = getLanguageRule(options.locale);
95
+ const parts = [
96
+ `<!--- Kilo Code Agent Config --->`,
97
+ `# ${agent.name} ${agent.emoji}`,
98
+ `**Role**: ${agent.role}\n`,
99
+ `## Instructions`,
100
+ agent.systemPrompt.trim(),
101
+ '\n'
102
+ ];
103
+
104
+ const allRules = [languageRule, ...(agent.rules || [])];
105
+
106
+ if (allRules.length > 0) {
107
+ parts.push(`## Constraints`);
108
+ allRules.forEach(rule => parts.push(`- ${rule}`));
109
+ }
110
+
111
+ return parts.join('\n');
112
+ }
113
+
114
+ /**
115
+ * Converte para Instruções do GitHub Copilot (.github/copilot-instructions.md)
116
+ */
117
+ function toCopilotInstructions(agent, options = {}) {
118
+ const languageRule = getLanguageRule(options.locale);
119
+ const parts = [
120
+ `<!-- GitHub Copilot Instructions for ${agent.name} -->`,
121
+ `# Identity and Role`,
122
+ `You are **${agent.name}** ${agent.emoji}.`,
123
+ `**Role**: ${agent.role}`,
124
+ `\n## Core Instructions`,
125
+ agent.systemPrompt.trim(),
126
+ '\n'
127
+ ];
128
+
129
+ const allRules = [languageRule, ...(agent.rules || [])];
130
+
131
+ if (allRules.length > 0) {
132
+ parts.push(`## Rules & Guidelines`);
133
+ allRules.forEach(rule => parts.push(`- ${rule}`));
134
+ }
135
+
136
+ // Adiciona uma seção de estilo de resposta para garantir conformidade
137
+ parts.push(`\n## Response Style`);
138
+ parts.push(`- Be concise and objective.`);
139
+ parts.push(`- Follow the project conventions defined in the workspace.`);
140
+
141
+ return parts.join('\n');
142
+ }
143
+
144
+ /**
145
+ * Converte para Cursor Rules (.mdc)
146
+ * Inclui Frontmatter para Contexto
147
+ */
148
+ function toCursorMDC(agent, options = {}) {
149
+ const languageRule = getLanguageRule(options.locale);
150
+ // Tenta inferir globs baseados no papel do agente
151
+ let globs = "*";
152
+ const roleLower = agent.slug.toLowerCase();
153
+
154
+ if (roleLower.includes('test') || roleLower.includes('qa')) globs = "*.test.*, *.spec.*, **/tests/**";
155
+ if (roleLower.includes('css') || roleLower.includes('style')) globs = "*.css, *.scss, *.tailwind";
156
+ if (roleLower.includes('sql') || roleLower.includes('db')) globs = "*.sql, *.prisma, *.schema";
157
+
158
+ const allRules = [languageRule, ...(agent.rules || [])];
159
+
160
+ return `---
161
+ description: ${agent.description || agent.role}
162
+ globs: ${globs}
163
+ ---
164
+ # ${agent.name} ${agent.emoji}
165
+
166
+ Role: ${agent.role}
167
+
168
+ ## Instructions
169
+ ${agent.systemPrompt.trim()}
170
+
171
+ ${allRules.length > 0 ? '## Rules\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
172
+ `;
173
+ }
174
+
175
+ /**
176
+ * Converte para Windsurf Workflow (.windsurf/workflows/*.md)
177
+ * Cascade reconhece esses arquivos como comandos de workflow
178
+ */
179
+ function toWindsurfRules(agent, options = {}) {
180
+ const languageRule = getLanguageRule(options.locale);
181
+ const allRules = [languageRule, ...(agent.rules || [])];
182
+
183
+ return `# ${agent.name} ${agent.emoji} Rules
184
+
185
+ Role: ${agent.role}
186
+
187
+ ## Core Logic
188
+ ${agent.systemPrompt.trim()}
189
+
190
+ ${allRules.length > 0 ? '## Guidelines\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
191
+ `;
192
+ }
193
+
194
+ /**
195
+ * Converte para Claude Code Command (.claude/commands/agents/*.md)
196
+ */
197
+ function toClaudeCommand(agent, options = {}) {
198
+ const languageRule = getLanguageRule(options.locale);
199
+ const allRules = [languageRule, ...(agent.rules || [])];
200
+
201
+ return `---
202
+ name: Agent: ${agent.name}
203
+ description: ${agent.description || agent.role}
204
+ category: Agents
205
+ ---
206
+ # ${agent.name} ${agent.emoji}
207
+
208
+ Role: ${agent.role}
209
+
210
+ ## Instructions
211
+ ${agent.systemPrompt.trim()}
212
+
213
+ ${allRules.length > 0 ? '## Rules\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
214
+ `;
215
+ }
216
+
217
+ /**
218
+ * Converte para System Prompt Puro (OpenAI/Claude/Web)
219
+ */
220
+ function toPlainSystemPrompt(agent, options = {}) {
221
+ const languageRule = getLanguageRule(options.locale);
222
+ const allRules = [languageRule, ...(agent.rules || [])];
223
+
224
+ return `You are ${agent.name} ${agent.emoji}
225
+ Role: ${agent.role}
226
+
227
+ [SYSTEM INSTRUCTIONS]
228
+ ${agent.systemPrompt.trim()}
229
+
230
+ ${allRules.length > 0 ? '[GUIDELINES]\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
231
+ `;
232
+ }
233
+
234
+ /**
235
+ * Converte para Trae Instructions
236
+ */
237
+ function toTraeRules(agent, options = {}) {
238
+ const languageRule = getLanguageRule(options.locale);
239
+ const allRules = [languageRule, ...(agent.rules || [])];
240
+
241
+ return `<!-- Trae Workspace Rules -->
242
+ # ${agent.name} ${agent.emoji}
243
+
244
+ **Role**: ${agent.role}
245
+
246
+ ## Context & Instructions
247
+ ${agent.systemPrompt.trim()}
248
+
249
+ ${allRules.length > 0 ? '## Constraints\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
250
+ `;
251
+ }
252
+
253
+ /**
254
+ * Converte para OpenCode Agent (.opencode/agent/*.md)
255
+ */
256
+ function toOpenCodeAgent(agent, options = {}) {
257
+ const languageRule = getLanguageRule(options.locale);
258
+ const allRules = [languageRule, ...(agent.rules || [])];
259
+
260
+ // Configurar permissões baseado no tipo de agente
261
+ const isReadOnly = agent.slug.includes('review') || agent.slug.includes('audit') || agent.name.includes('Architect') || agent.role.includes('QA') || agent.role.includes('Review');
262
+ const tools = {
263
+ write: !isReadOnly,
264
+ edit: !isReadOnly,
265
+ bash: !isReadOnly
266
+ };
267
+
268
+ const frontmatter = {
269
+ description: agent.description || agent.role,
270
+ mode: 'subagent',
271
+ temperature: 0.3,
272
+ tools
273
+ };
274
+
275
+ const frontmatterStr = Object.entries(frontmatter)
276
+ .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
277
+ .join('\n');
278
+
279
+ return `---
280
+ ${frontmatterStr}
281
+ ---
282
+
283
+ # ${agent.name} ${agent.emoji}
284
+
285
+ **Role**: ${agent.role}
286
+
287
+ ${agent.systemPrompt.trim()}
288
+
289
+ ## Rules
290
+ ${allRules.map(rule => `- ${rule}`).join('\n')}
291
+ `;
292
+ }
293
+
294
+ /**
295
+ * Converte para Trae Instructions
296
+ */
297
+ function toTraeRules(agent, options = {}) {
298
+ const languageRule = getLanguageRule(options.locale);
299
+ const allRules = [languageRule, ...(agent.rules || [])];
300
+
301
+ return `<!-- Trae Workspace Rules -->
302
+ # ${agent.name} ${agent.emoji}
303
+
304
+ **Role**: ${agent.role}
305
+
306
+ ## Context & Instructions
307
+ ${agent.systemPrompt.trim()}
308
+
309
+ ${allRules.length > 0 ? '## Constraints\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
310
+ }
311
+
312
+ module.exports = {
313
+ toGeminiTOML,
314
+ toRooConfig,
315
+ toKiloMarkdown,
316
+ toCopilotInstructions,
317
+ toCursorMDC,
318
+ toWindsurfRules,
319
+ toClaudeCommand,
320
+ toPlainSystemPrompt,
321
+ toOpenCodeAgent
322
+ };