sdd-toolkit 1.5.0 → 1.8.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 +339 -155
- package/README.pt.md +334 -0
- package/definitions/{dev.coder.yaml → sdd-coder.yaml} +15 -22
- package/definitions/sdd-feature.yaml +74 -0
- package/definitions/sdd-log.yaml +61 -0
- package/definitions/sdd-project.yaml +108 -0
- package/definitions/sdd-requirements.yaml +71 -0
- package/definitions/sdd-review.yaml +88 -0
- package/definitions/sdd.yaml +29 -0
- package/package.json +42 -41
- package/src/commands/view.js +18 -0
- package/src/index.js +354 -272
- package/src/lib/agents.js +1 -1
- package/src/lib/dashboard.js +188 -0
- package/src/lib/docs.js +2 -1
- package/src/lib/messages.js +57 -9
- package/src/lib/transformers.js +325 -239
- package/src/scripts/archive.js +5 -5
- package/src/scripts/reset.js +4 -4
- package/src/scripts/status.js +7 -7
- package/definitions/dev.auditor.yaml +0 -66
- package/definitions/dev.feature.yaml +0 -105
- package/definitions/dev.log.yaml +0 -90
- package/definitions/dev.milestone.yaml +0 -75
- package/definitions/dev.ops.yaml +0 -51
- package/definitions/dev.project.yaml +0 -106
- package/definitions/dev.requirements.yaml +0 -91
- package/definitions/dev.review.yaml +0 -61
- package/definitions/dev.tasks.yaml +0 -84
- package/templates/milestones.md +0 -14
package/src/index.js
CHANGED
|
@@ -1,284 +1,366 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const fsp = require('fs/promises');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
const { intro, outro, multiselect, spinner, note, select, text } = require('@clack/prompts');
|
|
7
|
-
const pc = require('picocolors');
|
|
8
|
-
|
|
9
|
-
// Internal Modules
|
|
10
|
-
const { loadAgents } = require('./lib/agents');
|
|
11
|
-
const { STACK_PROFILES } = require('./lib/profiles');
|
|
12
|
-
const { setLocale, t, getLocale } = require('./lib/i18n');
|
|
13
|
-
const {
|
|
14
|
-
toGeminiTOML,
|
|
15
|
-
toRooConfig,
|
|
16
|
-
toKiloMarkdown,
|
|
17
|
-
toCopilotInstructions,
|
|
18
|
-
toCursorMDC,
|
|
19
|
-
toWindsurfRules,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (fs.existsSync(path.join(process.cwd(), '.
|
|
68
|
-
if (fs.existsSync(path.join(process.cwd(), '.
|
|
69
|
-
if (fs.existsSync(path.join(process.cwd(), '.
|
|
70
|
-
if (fs.existsSync(path.join(process.cwd(), '.
|
|
71
|
-
if (fs.existsSync(path.join(process.cwd(), '.
|
|
72
|
-
if (fs.existsSync(path.join(process.cwd(), '
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
{ value: '
|
|
139
|
-
{ value: '
|
|
140
|
-
{ value: '
|
|
141
|
-
{ value: '
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const fsp = require('fs/promises');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { intro, outro, multiselect, spinner, note, select, text } = require('@clack/prompts');
|
|
7
|
+
const pc = require('picocolors');
|
|
8
|
+
|
|
9
|
+
// Internal Modules
|
|
10
|
+
const { loadAgents } = require('./lib/agents');
|
|
11
|
+
const { STACK_PROFILES } = require('./lib/profiles');
|
|
12
|
+
const { setLocale, t, getLocale } = require('./lib/i18n');
|
|
13
|
+
const {
|
|
14
|
+
toGeminiTOML,
|
|
15
|
+
toRooConfig,
|
|
16
|
+
toKiloMarkdown,
|
|
17
|
+
toCopilotInstructions,
|
|
18
|
+
toCursorMDC,
|
|
19
|
+
toWindsurfRules,
|
|
20
|
+
toClaudeCommand,
|
|
21
|
+
toPlainSystemPrompt,
|
|
22
|
+
toTraeRules,
|
|
23
|
+
toOpenCodeAgent
|
|
24
|
+
} = require('./lib/transformers');
|
|
25
|
+
const { generateWorkflowGuide } = require('./lib/docs');
|
|
26
|
+
const { view } = require('./commands/view');
|
|
27
|
+
|
|
28
|
+
async function main() {
|
|
29
|
+
console.clear();
|
|
30
|
+
|
|
31
|
+
const args = process.argv.slice(2);
|
|
32
|
+
|
|
33
|
+
if (args[0] === 'view') {
|
|
34
|
+
await view();
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const isUpgrade = args.includes('upgrade') || args.includes('--upgrade');
|
|
39
|
+
|
|
40
|
+
// 0. Language Selection
|
|
41
|
+
if (!isUpgrade) {
|
|
42
|
+
intro(pc.bgMagenta(pc.white(' UNIVERSAL SPEC CLI ')));
|
|
43
|
+
|
|
44
|
+
const lang = await select({
|
|
45
|
+
message: 'Select Language / Selecione o Idioma / Seleccione el Idioma',
|
|
46
|
+
options: [
|
|
47
|
+
{ value: 'en', label: 'English' },
|
|
48
|
+
{ value: 'pt_br', label: 'Português (Brasil)' },
|
|
49
|
+
{ value: 'es', label: 'Español' }
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (typeof lang === 'symbol') {
|
|
54
|
+
outro(pc.yellow('Operation cancelled.'));
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
setLocale(lang);
|
|
59
|
+
} else {
|
|
60
|
+
setLocale('en');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (isUpgrade) {
|
|
64
|
+
intro(pc.bgBlue(pc.white(t('INTRO.UPGRADE_TITLE'))));
|
|
65
|
+
|
|
66
|
+
const tools = [];
|
|
67
|
+
if (fs.existsSync(path.join(process.cwd(), '.gemini'))) tools.push('gemini');
|
|
68
|
+
if (fs.existsSync(path.join(process.cwd(), '.roo'))) tools.push('roo');
|
|
69
|
+
if (fs.existsSync(path.join(process.cwd(), '.cline'))) tools.push('cline');
|
|
70
|
+
if (fs.existsSync(path.join(process.cwd(), '.cursor'))) tools.push('cursor');
|
|
71
|
+
if (fs.existsSync(path.join(process.cwd(), '.windsurf'))) tools.push('windsurf');
|
|
72
|
+
if (fs.existsSync(path.join(process.cwd(), '.claude'))) tools.push('claude');
|
|
73
|
+
if (fs.existsSync(path.join(process.cwd(), '.trae'))) tools.push('trae');
|
|
74
|
+
if (fs.existsSync(path.join(process.cwd(), '.kilocode'))) tools.push('kilo');
|
|
75
|
+
if (fs.existsSync(path.join(process.cwd(), '.github'))) tools.push('copilot');
|
|
76
|
+
if (fs.existsSync(path.join(process.cwd(), '.roo'))) tools.push('roo');
|
|
77
|
+
if (fs.existsSync(path.join(process.cwd(), '.opencode'))) tools.push('opencode');
|
|
78
|
+
if (fs.existsSync(path.join(process.cwd(), 'prompts'))) tools.push('web');
|
|
79
|
+
|
|
80
|
+
if (tools.length === 0) {
|
|
81
|
+
note(t('UPGRADE.NO_CONFIG'), t('UPGRADE.NO_CONFIG_TITLE'));
|
|
82
|
+
} else {
|
|
83
|
+
note(t('UPGRADE.DETECTED_TOOLS', tools.join(', ')), t('UPGRADE.DETECTED_TITLE'));
|
|
84
|
+
await processAgentsInstallation(tools, { locale: getLocale() });
|
|
85
|
+
outro(pc.green(t('UPGRADE.SUCCESS')));
|
|
86
|
+
process.exit(0);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 1. Automatic Scaffold
|
|
91
|
+
const s = spinner();
|
|
92
|
+
s.start(t('SCAFFOLD.LOADING'));
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const stats = generateWorkflowGuide(process.cwd());
|
|
96
|
+
if (stats.created > 0) {
|
|
97
|
+
s.stop(`${t('SCAFFOLD.SUCCESS')} (${stats.created} new, ${stats.verified} verified)`);
|
|
98
|
+
} else {
|
|
99
|
+
s.stop(t('SCAFFOLD.ALREADY_EXISTS'));
|
|
100
|
+
}
|
|
101
|
+
} catch (e) {
|
|
102
|
+
s.stop(pc.red(t('SCAFFOLD.ERROR')));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 2. Feature 5: Stack Selection
|
|
106
|
+
const stackOptions = Object.entries(STACK_PROFILES).map(([key, profile]) => ({
|
|
107
|
+
value: key,
|
|
108
|
+
label: profile.label
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
const stackProfile = await select({
|
|
112
|
+
message: t('SETUP.STACK_SELECT'),
|
|
113
|
+
options: stackOptions,
|
|
114
|
+
initialValue: 'generic'
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (typeof stackProfile === 'symbol') {
|
|
118
|
+
outro(pc.yellow(t('GENERAL.CANCELLED')));
|
|
119
|
+
process.exit(0);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 3. Feature 3: Global Rules
|
|
123
|
+
const globalRules = await text({
|
|
124
|
+
message: t('SETUP.GLOBAL_RULES'),
|
|
125
|
+
placeholder: t('SETUP.GLOBAL_RULES_HINT'),
|
|
126
|
+
required: false
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (typeof globalRules === 'symbol') {
|
|
130
|
+
outro(pc.yellow(t('GENERAL.CANCELLED')));
|
|
131
|
+
process.exit(0);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 4. Tool Selection
|
|
135
|
+
const tools = await multiselect({
|
|
136
|
+
message: t('SETUP.TOOL_SELECT'),
|
|
137
|
+
options: [
|
|
138
|
+
{ value: 'gemini', label: t('TOOLS.GEMINI'), hint: '.gemini/commands/dev' },
|
|
139
|
+
{ value: 'roo', label: t('TOOLS.ROO'), hint: '.roo/commands/*.md' },
|
|
140
|
+
{ value: 'cline', label: t('TOOLS.CLINE'), hint: '.cline/ & custom_modes.json' },
|
|
141
|
+
{ value: 'cursor', label: t('TOOLS.CURSOR'), hint: '.cursor/commands/*.mdc' },
|
|
142
|
+
{ value: 'windsurf', label: t('TOOLS.WINDSURF'), hint: '.windsurf/workflows/*.md' },
|
|
143
|
+
{ value: 'claude', label: 'Claude Code', hint: '.claude/commands/agents/*.md' },
|
|
144
|
+
{ value: 'trae', label: t('TOOLS.TRAE'), hint: '.trae/instructions.md' },
|
|
145
|
+
{ value: 'kilo', label: t('TOOLS.KILO'), hint: '.kilocode/workflows/*.md' },
|
|
146
|
+
{ value: 'copilot', label: t('TOOLS.COPILOT'), hint: '.github/prompts/*.md' },
|
|
147
|
+
{ value: 'web', label: t('TOOLS.WEB'), hint: 'prompts/*.txt' },
|
|
148
|
+
{ value: 'opencode', label: t('TOOLS.OPENCODE'), hint: '.opencode/commands/*.md' }
|
|
149
|
+
],
|
|
150
|
+
required: true,
|
|
151
|
+
hint: t('SETUP.TOOL_HINT')
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (typeof tools === 'symbol') {
|
|
155
|
+
outro(pc.yellow(t('GENERAL.CANCELLED')));
|
|
156
|
+
process.exit(0);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!tools || tools.length === 0) {
|
|
160
|
+
outro(t('SETUP.NO_TOOLS'));
|
|
161
|
+
process.exit(0);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
await processAgentsInstallation(tools, { stackProfile, globalRules, locale: getLocale() });
|
|
165
|
+
|
|
166
|
+
outro(pc.green(t('SETUP.SUCCESS')));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function processAgentsInstallation(tools, options) {
|
|
170
|
+
const s = spinner();
|
|
171
|
+
s.start(t('INSTALL.LOADING'));
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
const validAgents = await loadAgents(options);
|
|
175
|
+
|
|
176
|
+
if (validAgents.length === 0) {
|
|
177
|
+
s.stop(t('INSTALL.NO_AGENTS'));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
s.message(t('INSTALL.INSTALLING', tools.join(', ')));
|
|
182
|
+
|
|
183
|
+
const toolHandlers = {
|
|
184
|
+
gemini: async (validAgents, options) => {
|
|
185
|
+
const targetDir = path.join(process.cwd(), '.gemini', 'commands', 'dev');
|
|
186
|
+
await fsp.mkdir(targetDir, { recursive: true });
|
|
187
|
+
|
|
188
|
+
await Promise.all(
|
|
189
|
+
validAgents.map((agent) => {
|
|
190
|
+
const toml = toGeminiTOML(agent, options);
|
|
191
|
+
const fileName = `${agent.originalName}.toml`;
|
|
192
|
+
return fsp.writeFile(path.join(targetDir, fileName), toml);
|
|
193
|
+
})
|
|
194
|
+
);
|
|
195
|
+
},
|
|
196
|
+
roo: async (validAgents, options) => {
|
|
197
|
+
const targetDir = path.join(process.cwd(), '.roo', 'commands');
|
|
183
198
|
await fsp.mkdir(targetDir, { recursive: true });
|
|
184
199
|
|
|
185
|
-
await Promise.all(
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const targetDir = path.join(process.cwd(),
|
|
200
|
+
await Promise.all(
|
|
201
|
+
validAgents.map((agent) => {
|
|
202
|
+
const md = toOpenCodeAgent(agent, options);
|
|
203
|
+
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
},
|
|
207
|
+
cline: async (validAgents, options) => {
|
|
208
|
+
const targetDir = path.join(process.cwd(), '.cline');
|
|
209
|
+
await fsp.mkdir(targetDir, { recursive: true });
|
|
210
|
+
|
|
211
|
+
await Promise.all(
|
|
212
|
+
validAgents.map((agent) => {
|
|
213
|
+
const md = toKiloMarkdown(agent, options);
|
|
214
|
+
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
215
|
+
})
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const modes = validAgents.map((agent) => toRooConfig(agent, agent.slug, options));
|
|
219
|
+
const jsonContent = JSON.stringify({ customModes: modes }, null, 2);
|
|
220
|
+
await fsp.writeFile(path.join(process.cwd(), 'cline_custom_modes.json'), jsonContent);
|
|
221
|
+
},
|
|
222
|
+
windsurf: async (validAgents, options) => {
|
|
223
|
+
const targetDir = path.join(process.cwd(), '.windsurf', 'workflows');
|
|
224
|
+
await fsp.mkdir(targetDir, { recursive: true });
|
|
225
|
+
|
|
226
|
+
await Promise.all(
|
|
227
|
+
validAgents.map((agent) => {
|
|
228
|
+
const md = toWindsurfRules(agent, options);
|
|
229
|
+
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
230
|
+
})
|
|
231
|
+
);
|
|
232
|
+
},
|
|
233
|
+
claude: async (validAgents, options) => {
|
|
234
|
+
const targetDir = path.join(process.cwd(), '.claude', 'commands', 'agents');
|
|
194
235
|
await fsp.mkdir(targetDir, { recursive: true });
|
|
195
236
|
|
|
196
|
-
await Promise.all(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
237
|
+
await Promise.all(
|
|
238
|
+
validAgents.map((agent) => {
|
|
239
|
+
const md = toClaudeCommand(agent, options);
|
|
240
|
+
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
241
|
+
})
|
|
242
|
+
);
|
|
243
|
+
},
|
|
244
|
+
cursor: async (validAgents, options) => {
|
|
245
|
+
const commandsDir = path.join(process.cwd(), '.cursor', 'commands');
|
|
246
|
+
await fsp.mkdir(commandsDir, { recursive: true });
|
|
247
|
+
|
|
248
|
+
await Promise.all(
|
|
249
|
+
validAgents.map((agent) => {
|
|
250
|
+
const mdc = toCursorMDC(agent, options);
|
|
251
|
+
return fsp.writeFile(path.join(commandsDir, `${agent.slug}.mdc`), mdc);
|
|
252
|
+
})
|
|
253
|
+
);
|
|
254
|
+
},
|
|
255
|
+
kilo: async (validAgents, options) => {
|
|
256
|
+
const targetDir = path.join(process.cwd(), '.kilocode', 'workflows');
|
|
208
257
|
await fsp.mkdir(targetDir, { recursive: true });
|
|
209
|
-
|
|
210
|
-
await Promise.all(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
258
|
+
|
|
259
|
+
await Promise.all(
|
|
260
|
+
validAgents.map((agent) => {
|
|
261
|
+
const md = toKiloMarkdown(agent, options);
|
|
262
|
+
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
263
|
+
})
|
|
264
|
+
);
|
|
265
|
+
},
|
|
266
|
+
copilot: async (validAgents, options) => {
|
|
216
267
|
const githubDir = path.join(process.cwd(), '.github');
|
|
217
|
-
const
|
|
218
|
-
await fsp.mkdir(
|
|
268
|
+
const promptsDir = path.join(githubDir, 'prompts');
|
|
269
|
+
await fsp.mkdir(promptsDir, { recursive: true });
|
|
219
270
|
|
|
220
|
-
await Promise.all(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
271
|
+
await Promise.all(
|
|
272
|
+
validAgents.map((agent) => {
|
|
273
|
+
const md = toCopilotInstructions(agent, options);
|
|
274
|
+
return fsp.writeFile(path.join(promptsDir, `${agent.slug}.md`), md);
|
|
275
|
+
})
|
|
276
|
+
);
|
|
224
277
|
|
|
225
|
-
const mainAgent = validAgents.find(a => a.slug.includes('coder')) || validAgents[0];
|
|
278
|
+
const mainAgent = validAgents.find((a) => a.slug.includes('coder')) || validAgents[0];
|
|
226
279
|
const mainInstructions = toCopilotInstructions(mainAgent, options);
|
|
227
|
-
await fsp.writeFile(path.join(githubDir, '
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const
|
|
231
|
-
await fsp.mkdir(
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
await
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
else if (tool === 'web') {
|
|
252
|
-
const targetDir = path.join(process.cwd(), 'prompts');
|
|
280
|
+
await fsp.writeFile(path.join(githubDir, 'prompts.md'), mainInstructions);
|
|
281
|
+
},
|
|
282
|
+
trae: async (validAgents, options) => {
|
|
283
|
+
const traeDir = path.join(process.cwd(), '.trae');
|
|
284
|
+
await fsp.mkdir(traeDir, { recursive: true });
|
|
285
|
+
|
|
286
|
+
const mainAgent = validAgents.find((a) => a.slug.includes('coder')) || validAgents[0];
|
|
287
|
+
const rules = toTraeRules(mainAgent, options);
|
|
288
|
+
await fsp.writeFile(path.join(traeDir, 'instructions.md'), rules);
|
|
289
|
+
},
|
|
290
|
+
web: async (validAgents, options) => {
|
|
291
|
+
const targetDir = path.join(process.cwd(), 'prompts');
|
|
292
|
+
await fsp.mkdir(targetDir, { recursive: true });
|
|
293
|
+
|
|
294
|
+
await Promise.all(
|
|
295
|
+
validAgents.map((agent) => {
|
|
296
|
+
const txt = toPlainSystemPrompt(agent, options);
|
|
297
|
+
return fsp.writeFile(path.join(targetDir, `${agent.slug}.txt`), txt);
|
|
298
|
+
})
|
|
299
|
+
);
|
|
300
|
+
},
|
|
301
|
+
opencode: async (validAgents, options) => {
|
|
302
|
+
const targetDir = path.join(process.cwd(), '.opencode', 'commands');
|
|
253
303
|
await fsp.mkdir(targetDir, { recursive: true });
|
|
254
304
|
|
|
255
|
-
await Promise.all(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
305
|
+
await Promise.all(
|
|
306
|
+
validAgents.map((agent) => {
|
|
307
|
+
const md = toOpenCodeAgent(agent, options);
|
|
308
|
+
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
309
|
+
})
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
// Generate AGENTS.md with interaction rules and agent location
|
|
313
|
+
const agentsMdPath = path.join(process.cwd(), 'AGENTS.md');
|
|
314
|
+
let agentsMdContent = `# Interaction Rules
|
|
315
|
+
|
|
316
|
+
- Always respond to the user in the language they initially interact in; if they interact in English, respond in English, if they interact in Portuguese, respond in Portuguese.
|
|
317
|
+
- If possible, display reasoning in the user's language as well.
|
|
318
|
+
- Be didactic when explaining things, focus on providing complete responses and not just summaries.
|
|
319
|
+
- Whenever possible, provide examples to illustrate concepts.
|
|
320
|
+
|
|
321
|
+
# Allowed Commands
|
|
322
|
+
|
|
323
|
+
- Never execute rm or rm -rf commands without confirming with the user.
|
|
324
|
+
- Whenever possible, use more specific commands instead of generic ones.
|
|
325
|
+
- Be cautious when using commands that may affect critical systems, such as shutdown or reboot.
|
|
326
|
+
- For commands that may affect files or directories, always confirm with the user before executing.
|
|
327
|
+
- Never execute commands that require administrative privileges (sudo, admin) without explicit permission from the user.
|
|
328
|
+
- Avoid running background processes or daemons unless explicitly requested.
|
|
329
|
+
- Be cautious when using commands that alter network settings, firewall configurations, or external connections.
|
|
330
|
+
- Always quote file paths that contain spaces to avoid interpretation errors.
|
|
331
|
+
- For package installation commands (npm install, pip install, etc.), confirm that the user has control over dependencies and versions.
|
|
332
|
+
- Avoid irreversible git operations (such as force push or reset --hard) without confirmation.
|
|
333
|
+
|
|
334
|
+
# Agent Location
|
|
335
|
+
|
|
336
|
+
Custom agents are located in .opencode/commands/`;
|
|
337
|
+
|
|
338
|
+
let userRules = '';
|
|
339
|
+
if (options.globalRules && options.globalRules.trim()) {
|
|
340
|
+
userRules = '\n\n# User Specified Rules\n\n' + options.globalRules.split('\n').filter(line => line.trim()).map(line => '- ' + line.trim()).join('\n');
|
|
341
|
+
}
|
|
342
|
+
agentsMdContent += userRules;
|
|
343
|
+
|
|
344
|
+
await fsp.writeFile(agentsMdPath, agentsMdContent);
|
|
259
345
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
main().catch(console.error);
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
for (const tool of tools) {
|
|
349
|
+
const handler = toolHandlers[tool];
|
|
350
|
+
if (handler) {
|
|
351
|
+
await handler(validAgents, options);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
s.stop(t('INSTALL.FINISHED'));
|
|
356
|
+
|
|
357
|
+
if (tools.includes('roo') || tools.includes('cline')) {
|
|
358
|
+
note(t('INSTALL.ROO_WARNING'), t('INSTALL.ROO_WARNING_TITLE'));
|
|
359
|
+
}
|
|
360
|
+
} catch (e) {
|
|
361
|
+
s.stop(pc.red(`${t('INSTALL.FAILED')}: ${e.message}`));
|
|
362
|
+
process.exit(1);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
main().catch(console.error);
|