@ronaldjdevfs/forge 1.2.0 → 1.3.0-beta
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 +36 -21
- package/package.json +7 -2
- package/skills/forge/SKILL.md +11 -6
- package/skills/forge/scripts/forgeSentinel-lib.mjs +86 -0
- package/skills/forge/scripts/forgeSentinel.mjs +184 -0
- package/skills/forge/scripts/forgeSmith-admin.mjs +104 -0
- package/skills/forge/scripts/forgeSmith.mjs +164 -0
- package/skills/forge/scripts/pin.mjs +10 -3
- package/skills/forge/scripts/posttool.mjs +17 -211
- package/skills/forge/templates/agents/SKILL.md.template +283 -0
- package/skills/forge/templates/agents/agents/hooks.json +18 -0
- package/skills/forge/templates/agents/claude/CLAUDE.md +17 -16
- package/skills/forge/templates/agents/claude/settings.local.json +18 -0
- package/skills/forge/templates/agents/codex/hooks.json +18 -0
- package/skills/forge/templates/agents/cursor/.cursorrules +22 -5
- package/skills/forge/templates/agents/cursor/hooks.json +11 -0
- package/skills/forge/templates/agents/gemini/SKILL.md +13 -0
- package/skills/forge/tests/core.test.mjs +4 -4
- package/src/agents.mjs +35 -2
- package/src/cli.js +86 -26
- package/src/wizard.mjs +142 -90
package/src/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { copyFileSync, mkdirSync, existsSync, writeFileSync, readFileSync, cpSync } from "fs";
|
|
3
|
+
import { copyFileSync, mkdirSync, existsSync, writeFileSync, readFileSync, cpSync, readdirSync } from "fs";
|
|
4
4
|
import { join, dirname, relative } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { execSync } from "child_process";
|
|
@@ -11,6 +11,14 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
11
11
|
const SKILL_SRC = join(__dirname, "..", "skills", "forge");
|
|
12
12
|
const AGENTS_TEMPLATES = join(SKILL_SRC, "templates", "agents");
|
|
13
13
|
|
|
14
|
+
const AGENT_CONFIGS = {
|
|
15
|
+
claude: { dir: ".claude", template: "claude", skillPath: ".claude/skills/forge", need: ["CLAUDE.md", "settings.local.json"], postInstall: "forgeSentinel" },
|
|
16
|
+
cursor: { dir: ".cursor", template: "cursor", skillPath: ".cursor/skills/forge", need: [".cursorrules", "hooks.json"], postInstall: "forgeSmith" },
|
|
17
|
+
codex: { dir: ".agents", template: "codex", skillPath: ".agents/skills/forge", need: ["hooks.json"], postInstall: "forgeSentinel" },
|
|
18
|
+
gemini: { dir: ".gemini", template: "gemini", skillPath: ".gemini/skills/forge", need: ["SKILL.md"], postInstall: null },
|
|
19
|
+
agents: { dir: ".agents", template: "agents", skillPath: ".agents/skills/forge", need: ["hooks.json"], postInstall: "forgeSentinel" },
|
|
20
|
+
};
|
|
21
|
+
|
|
14
22
|
function getTargetDir(global) {
|
|
15
23
|
if (global) {
|
|
16
24
|
const home = process.env.HOME || process.env.USERPROFILE;
|
|
@@ -137,40 +145,70 @@ async function installOpenCode(isGlobal = false) {
|
|
|
137
145
|
log.success("OpenCode configurado correctamente");
|
|
138
146
|
}
|
|
139
147
|
|
|
140
|
-
async function
|
|
141
|
-
const
|
|
142
|
-
|
|
148
|
+
async function installAgentTemplates(agentDir, agentName) {
|
|
149
|
+
const config = AGENT_CONFIGS[agentName];
|
|
150
|
+
if (!config) return;
|
|
143
151
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
152
|
+
const templateDir = join(AGENTS_TEMPLATES, config.template);
|
|
153
|
+
if (!existsSync(templateDir)) {
|
|
154
|
+
log.error(`Template para ${agentName} no encontrado en ${templateDir}`);
|
|
155
|
+
return;
|
|
147
156
|
}
|
|
148
157
|
|
|
149
158
|
const s = spinner();
|
|
150
|
-
s.start(
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
s.start(`Copiando templates para ${agentName} en ${agentDir}/`);
|
|
160
|
+
|
|
161
|
+
mkdirSync(agentDir, { recursive: true });
|
|
162
|
+
|
|
163
|
+
// Copy skill into <agentDir>/skills/forge/
|
|
164
|
+
const skillDest = join(agentDir, "skills", "forge");
|
|
165
|
+
cpSync(SKILL_SRC, skillDest, { recursive: true, force: true });
|
|
153
166
|
|
|
154
|
-
|
|
167
|
+
// Copy template files (hooks, CLAUDE.md, .cursorrules, etc.)
|
|
168
|
+
for (const entry of readdirSync(templateDir)) {
|
|
169
|
+
const srcFile = join(templateDir, entry);
|
|
170
|
+
const destFile = join(agentDir, entry);
|
|
171
|
+
cpSync(srcFile, destFile, { recursive: true, force: true });
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Render SKILL.md with agent-specific path
|
|
175
|
+
const templatePath = join(AGENTS_TEMPLATES, "SKILL.md.template");
|
|
176
|
+
if (existsSync(templatePath)) {
|
|
177
|
+
const template = readFileSync(templatePath, "utf-8");
|
|
178
|
+
const rendered = template.replace(/\{\{AGENT_PATH\}\}/g, config.skillPath);
|
|
179
|
+
writeFileSync(join(skillDest, "SKILL.md"), rendered, "utf-8");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
s.stop(`${agentName} configurado en ${agentDir}/`);
|
|
183
|
+
log.success(`${agentName} listo (skill + ${config.postInstall || "templates"})`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function installCursor() {
|
|
187
|
+
await installAgentTemplates(join(process.cwd(), ".cursor"), "cursor");
|
|
155
188
|
}
|
|
156
189
|
|
|
157
190
|
async function installClaude() {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const dest = join(claudeDir, "CLAUDE.md");
|
|
191
|
+
await installAgentTemplates(join(process.cwd(), ".claude"), "claude");
|
|
192
|
+
}
|
|
161
193
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
194
|
+
async function installCodex() {
|
|
195
|
+
// Codex hooks point to .agents/skills/forge/ via git root
|
|
196
|
+
await installAgentTemplates(join(process.cwd(), ".agents"), "codex");
|
|
197
|
+
// Also copy hooks.json into .codex/ so Codex CLI picks it up
|
|
198
|
+
const codexDir = join(process.cwd(), ".codex");
|
|
199
|
+
mkdirSync(codexDir, { recursive: true });
|
|
200
|
+
const hooksSrc = join(AGENTS_TEMPLATES, "codex", "hooks.json");
|
|
201
|
+
if (existsSync(hooksSrc)) {
|
|
202
|
+
cpSync(hooksSrc, join(codexDir, "hooks.json"), { force: true });
|
|
165
203
|
}
|
|
204
|
+
}
|
|
166
205
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
copyFileSync(src, dest);
|
|
171
|
-
s.stop(".claude/CLAUDE.md creado");
|
|
206
|
+
async function installGemini() {
|
|
207
|
+
await installAgentTemplates(join(process.cwd(), ".gemini"), "gemini");
|
|
208
|
+
}
|
|
172
209
|
|
|
173
|
-
|
|
210
|
+
async function installAgentsGeneric() {
|
|
211
|
+
await installAgentTemplates(join(process.cwd(), ".agents"), "agents");
|
|
174
212
|
}
|
|
175
213
|
|
|
176
214
|
async function installAgents(selected, isGlobal = false) {
|
|
@@ -185,6 +223,15 @@ async function installAgents(selected, isGlobal = false) {
|
|
|
185
223
|
case "claude":
|
|
186
224
|
await installClaude();
|
|
187
225
|
break;
|
|
226
|
+
case "codex":
|
|
227
|
+
await installCodex();
|
|
228
|
+
break;
|
|
229
|
+
case "gemini":
|
|
230
|
+
await installGemini();
|
|
231
|
+
break;
|
|
232
|
+
case "agents":
|
|
233
|
+
await installAgentsGeneric();
|
|
234
|
+
break;
|
|
188
235
|
}
|
|
189
236
|
}
|
|
190
237
|
}
|
|
@@ -200,10 +247,19 @@ USO
|
|
|
200
247
|
forge install --opencode Instalar solo para OpenCode
|
|
201
248
|
forge install --cursor Instalar solo para Cursor
|
|
202
249
|
forge install --claude Instalar solo para Claude Code
|
|
203
|
-
forge install --
|
|
250
|
+
forge install --codex Instalar solo para Codex CLI
|
|
251
|
+
forge install --gemini Instalar solo para Gemini Code Assist
|
|
252
|
+
forge install --all Instalar para todos los agentes detectados
|
|
204
253
|
forge install --global Instalar OpenCode globalmente (~/.config/opencode/)
|
|
205
254
|
forge install --help Mostrar esta ayuda
|
|
206
255
|
|
|
256
|
+
AGENTES SOPORTADOS
|
|
257
|
+
OpenCode, Claude Code, Cursor, Codex CLI, Gemini Code Assist, Agentes Genéricos
|
|
258
|
+
|
|
259
|
+
HOOKS
|
|
260
|
+
forgeSentinel (PostToolUse) — guardia arquitectónico post-escritura
|
|
261
|
+
forgeSmith (preToolUse) — guardia arquitectónico pre-escritura (Cursor)
|
|
262
|
+
|
|
207
263
|
OPCIONES
|
|
208
264
|
-g, --global Instalar OpenCode en ~/.config/opencode/skills/forge/
|
|
209
265
|
-h, --help Mostrar esta ayuda
|
|
@@ -223,6 +279,8 @@ async function main() {
|
|
|
223
279
|
const hasOpenCode = args.includes("--opencode");
|
|
224
280
|
const hasCursor = args.includes("--cursor");
|
|
225
281
|
const hasClaude = args.includes("--claude");
|
|
282
|
+
const hasCodex = args.includes("--codex");
|
|
283
|
+
const hasGemini = args.includes("--gemini");
|
|
226
284
|
const hasAll = args.includes("--all");
|
|
227
285
|
|
|
228
286
|
const subcommandIndex = args.indexOf("skills");
|
|
@@ -230,12 +288,14 @@ async function main() {
|
|
|
230
288
|
|
|
231
289
|
if (command === "install") {
|
|
232
290
|
if (hasAll) {
|
|
233
|
-
await installAgents(["opencode", "cursor", "claude"], isGlobal);
|
|
234
|
-
} else if (hasOpenCode || hasCursor || hasClaude) {
|
|
291
|
+
await installAgents(["opencode", "cursor", "claude", "codex", "gemini", "agents"], isGlobal);
|
|
292
|
+
} else if (hasOpenCode || hasCursor || hasClaude || hasCodex || hasGemini) {
|
|
235
293
|
const selected = [];
|
|
236
294
|
if (hasOpenCode) selected.push("opencode");
|
|
237
295
|
if (hasCursor) selected.push("cursor");
|
|
238
296
|
if (hasClaude) selected.push("claude");
|
|
297
|
+
if (hasCodex) selected.push("codex");
|
|
298
|
+
if (hasGemini) selected.push("gemini");
|
|
239
299
|
await installAgents(selected, isGlobal);
|
|
240
300
|
} else {
|
|
241
301
|
await runWizard();
|
package/src/wizard.mjs
CHANGED
|
@@ -93,6 +93,56 @@ function copyAgentTemplate(name, dest) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
const AGENT_SKILL_PATHS = {
|
|
97
|
+
claude: ".claude/skills/forge",
|
|
98
|
+
cursor: ".cursor/skills/forge",
|
|
99
|
+
codex: ".agents/skills/forge",
|
|
100
|
+
gemini: ".gemini/skills/forge",
|
|
101
|
+
agents: ".agents/skills/forge",
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
function installAgentTemplates(agentDir, agentName) {
|
|
105
|
+
const templateDir = join(AGENTS_TEMPLATES, agentName);
|
|
106
|
+
if (!existsSync(templateDir)) {
|
|
107
|
+
return { ok: false, error: `Template ${agentName} no encontrado` };
|
|
108
|
+
}
|
|
109
|
+
mkdirSync(agentDir, { recursive: true });
|
|
110
|
+
// Copy skill into <agentDir>/skills/forge/
|
|
111
|
+
const skillDest = join(agentDir, "skills", "forge");
|
|
112
|
+
cpSync(SKILL_SRC, skillDest, { recursive: true, force: true });
|
|
113
|
+
// Copy template files (hooks, CLAUDE.md, .cursorrules, etc.)
|
|
114
|
+
copyAgentTemplate(agentName, agentDir);
|
|
115
|
+
|
|
116
|
+
// Render SKILL.md with agent-specific path
|
|
117
|
+
const templatePath = join(AGENTS_TEMPLATES, "SKILL.md.template");
|
|
118
|
+
if (existsSync(templatePath)) {
|
|
119
|
+
const template = readFileSync(templatePath, "utf-8");
|
|
120
|
+
const skillPath = AGENT_SKILL_PATHS[agentName] || agentName;
|
|
121
|
+
const rendered = template.replace(/\{\{AGENT_PATH\}\}/g, skillPath);
|
|
122
|
+
writeFileSync(join(skillDest, "SKILL.md"), rendered, "utf-8");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Codex special case: also copy hooks.json to .codex/
|
|
126
|
+
if (agentName === "codex") {
|
|
127
|
+
const codexDir = join(process.cwd(), ".codex");
|
|
128
|
+
mkdirSync(codexDir, { recursive: true });
|
|
129
|
+
const hooksSrc = join(templateDir, "hooks.json");
|
|
130
|
+
if (existsSync(hooksSrc)) {
|
|
131
|
+
cpSync(hooksSrc, join(codexDir, "hooks.json"), { force: true });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return { ok: true, dest: agentDir };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const HOOK_LABELS = {
|
|
139
|
+
claude: "forgeSentinel (PostToolUse)",
|
|
140
|
+
cursor: "forgeSmith (preToolUse)",
|
|
141
|
+
codex: "forgeSentinel (PostToolUse)",
|
|
142
|
+
gemini: "—",
|
|
143
|
+
agents: "forgeSentinel (PostToolUse)",
|
|
144
|
+
};
|
|
145
|
+
|
|
96
146
|
// --- Welcome ---
|
|
97
147
|
|
|
98
148
|
async function welcomePhase() {
|
|
@@ -235,6 +285,10 @@ async function summaryPhase(agentSelection) {
|
|
|
235
285
|
console.log(` ${pc.bold("Componentes")}`);
|
|
236
286
|
console.log();
|
|
237
287
|
|
|
288
|
+
const hasHooks = agentSelection.selectedIds.some(id =>
|
|
289
|
+
["claude-project", "claude-global", "cursor-project", "codex-project", "codex-global", "agents-project"].includes(id)
|
|
290
|
+
);
|
|
291
|
+
|
|
238
292
|
const components = [
|
|
239
293
|
"Forge Skill",
|
|
240
294
|
"Reglas",
|
|
@@ -242,7 +296,8 @@ async function summaryPhase(agentSelection) {
|
|
|
242
296
|
"Comandos",
|
|
243
297
|
"Plantillas",
|
|
244
298
|
"Agentes",
|
|
245
|
-
|
|
299
|
+
hasHooks ? "forgeSentinel (PostToolUse) / forgeSmith (preToolUse)" : null,
|
|
300
|
+
].filter(Boolean);
|
|
246
301
|
for (const comp of components) {
|
|
247
302
|
console.log(` ${pc.green("\u2714")} ${comp}`);
|
|
248
303
|
}
|
|
@@ -275,102 +330,97 @@ async function summaryPhase(agentSelection) {
|
|
|
275
330
|
|
|
276
331
|
// --- Installation ---
|
|
277
332
|
|
|
333
|
+
const AGENT_MAP = {
|
|
334
|
+
"claude-global": { name: "claude", dir: () => join(HOME, ".claude"), verify: "CLAUDE.md" },
|
|
335
|
+
"claude-project": { name: "claude", dir: () => join(process.cwd(), ".claude"), verify: "CLAUDE.md" },
|
|
336
|
+
"cursor-project": { name: "cursor", dir: () => join(process.cwd(), ".cursor"), verify: ".cursorrules" },
|
|
337
|
+
"codex-project": { name: "codex", dir: () => join(process.cwd(), ".agents"), verify: "hooks.json" },
|
|
338
|
+
"codex-global": { name: "codex", dir: () => join(HOME, ".codex"), verify: "hooks.json" },
|
|
339
|
+
"gemini-project": { name: "gemini", dir: () => join(process.cwd(), ".gemini"), verify: "SKILL.md" },
|
|
340
|
+
"agents-project": { name: "agents", dir: () => join(process.cwd(), ".agents"), verify: "hooks.json" },
|
|
341
|
+
"opencode-global": null,
|
|
342
|
+
"opencode-project": null,
|
|
343
|
+
"copilot-project": null,
|
|
344
|
+
};
|
|
345
|
+
|
|
278
346
|
function buildAgentSteps(agent, cwd) {
|
|
279
347
|
const label = `${agent.label} (${agent.scope})`;
|
|
280
348
|
const s = (title, fn) => ({ title: `${pc.dim("\u2502")} ${title}`, task: fn });
|
|
281
349
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const steps = [];
|
|
304
|
-
steps.push(s("Copiando Skill en opencode/", async () => {
|
|
305
|
-
mkdirSync(dest, { recursive: true });
|
|
306
|
-
cpSync(SKILL_SRC, dest, { recursive: true, force: true });
|
|
307
|
-
return "Skill copiada";
|
|
308
|
-
}));
|
|
309
|
-
steps.push(s("Registrando comandos + dependencias", async () => {
|
|
310
|
-
generateCommands(configDir);
|
|
311
|
-
ensureDependencies(configDir);
|
|
312
|
-
return "Comandos y dependencias listos";
|
|
313
|
-
}));
|
|
314
|
-
steps.push(s("Verificando instalaci\u00f3n", async () => {
|
|
315
|
-
const ok = existsSync(join(dest, "scripts", "context.mjs"));
|
|
316
|
-
return ok ? "\u2714 Instalaci\u00f3n verificada" : "ERROR: Skill no encontrada";
|
|
317
|
-
}));
|
|
318
|
-
return { label, dest, steps };
|
|
319
|
-
}
|
|
350
|
+
// Handle special cases (opencode, copilot) separately
|
|
351
|
+
if (agent.id === "opencode-global") {
|
|
352
|
+
const dest = join(HOME, ".config", "opencode", "skills", "forge");
|
|
353
|
+
const configDir = join(HOME, ".config", "opencode");
|
|
354
|
+
const steps = [];
|
|
355
|
+
steps.push(s("Copiando Skill en opencode/", async () => {
|
|
356
|
+
mkdirSync(dest, { recursive: true });
|
|
357
|
+
cpSync(SKILL_SRC, dest, { recursive: true, force: true });
|
|
358
|
+
return "Skill copiada";
|
|
359
|
+
}));
|
|
360
|
+
steps.push(s("Registrando comandos + dependencias", async () => {
|
|
361
|
+
generateCommands(configDir);
|
|
362
|
+
ensureDependencies(configDir);
|
|
363
|
+
return "Comandos y dependencias listos";
|
|
364
|
+
}));
|
|
365
|
+
steps.push(s("Verificando instalaci\u00f3n", async () => {
|
|
366
|
+
const ok = existsSync(join(dest, "scripts", "context.mjs"));
|
|
367
|
+
return ok ? "\u2714 Instalaci\u00f3n verificada" : "ERROR: Skill no encontrada";
|
|
368
|
+
}));
|
|
369
|
+
return { label, dest, steps };
|
|
370
|
+
}
|
|
320
371
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
372
|
+
if (agent.id === "opencode-project") {
|
|
373
|
+
const dest = join(cwd, ".opencode", "skills", "forge");
|
|
374
|
+
const configDir = join(cwd, ".opencode");
|
|
375
|
+
const steps = [];
|
|
376
|
+
steps.push(s("Copiando Skill en .opencode/", async () => {
|
|
377
|
+
mkdirSync(dest, { recursive: true });
|
|
378
|
+
cpSync(SKILL_SRC, dest, { recursive: true, force: true });
|
|
379
|
+
return "Skill copiada";
|
|
380
|
+
}));
|
|
381
|
+
steps.push(s("Registrando comandos + dependencias", async () => {
|
|
382
|
+
generateCommands(configDir);
|
|
383
|
+
ensureDependencies(configDir);
|
|
384
|
+
return "Comandos y dependencias listos";
|
|
385
|
+
}));
|
|
386
|
+
steps.push(s("Verificando instalaci\u00f3n", async () => {
|
|
387
|
+
const ok = existsSync(join(dest, "scripts", "context.mjs"));
|
|
388
|
+
return ok ? "\u2714 Instalaci\u00f3n verificada" : "ERROR: Skill no encontrada";
|
|
389
|
+
}));
|
|
390
|
+
return { label, dest, steps };
|
|
391
|
+
}
|
|
341
392
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
393
|
+
if (agent.id === "copilot-project") {
|
|
394
|
+
const ghDir = join(cwd, ".github");
|
|
395
|
+
const dest = join(ghDir, "copilot-instructions.md");
|
|
396
|
+
const steps = [];
|
|
397
|
+
steps.push(s("Instalando reglas en .github/", async () => {
|
|
398
|
+
mkdirSync(ghDir, { recursive: true });
|
|
399
|
+
const src = join(AGENTS_TEMPLATES, "cursor", ".cursorrules");
|
|
400
|
+
if (existsSync(src)) copyFileSync(src, dest);
|
|
401
|
+
const ok = existsSync(dest);
|
|
402
|
+
return ok ? "Reglas instaladas" : "ERROR";
|
|
403
|
+
}));
|
|
404
|
+
return { label, dest, steps };
|
|
405
|
+
}
|
|
355
406
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
steps.push(s("Instalando Forge en .codex/", async () => {
|
|
360
|
-
mkdirSync(dest, { recursive: true });
|
|
361
|
-
copyAgentTemplate("cursor", dest);
|
|
362
|
-
cpSync(SKILL_SRC, join(dest, "forge"), { recursive: true, force: true });
|
|
363
|
-
return "Forge instalado";
|
|
364
|
-
}));
|
|
365
|
-
steps.push(s("Verificando instalaci\u00f3n", async () => {
|
|
366
|
-
return existsSync(dest) ? "\u2714 Instalaci\u00f3n verificada" : "ERROR";
|
|
367
|
-
}));
|
|
368
|
-
return { label, dest, steps };
|
|
369
|
-
}
|
|
407
|
+
// Generic agent types via AGENT_MAP
|
|
408
|
+
const map = AGENT_MAP[agent.id];
|
|
409
|
+
if (!map) return null;
|
|
370
410
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
411
|
+
const dest = map.dir();
|
|
412
|
+
const agentName = map.name;
|
|
413
|
+
const steps = [];
|
|
414
|
+
steps.push(s(`Instalando Forge + hooks en ${dest}/`, async () => {
|
|
415
|
+
const r = installAgentTemplates(dest, agentName);
|
|
416
|
+
return r.ok ? `Forge + ${HOOK_LABELS[agentName] || "templates"} instalados` : `ERROR: ${r.error}`;
|
|
417
|
+
}));
|
|
418
|
+
steps.push(s("Verificando instalaci\u00f3n", async () => {
|
|
419
|
+
const ok = existsSync(join(dest, "skills", "forge", "scripts", "context.mjs")) &&
|
|
420
|
+
existsSync(join(dest, map.verify));
|
|
421
|
+
return ok ? "\u2714 Instalaci\u00f3n verificada" : "ERROR: archivos no encontrados";
|
|
422
|
+
}));
|
|
423
|
+
return { label, dest, steps };
|
|
374
424
|
}
|
|
375
425
|
|
|
376
426
|
async function installPhase(result, cwd) {
|
|
@@ -465,7 +515,9 @@ export async function runWizard() {
|
|
|
465
515
|
console.log();
|
|
466
516
|
console.log(` \u2022 Reinicia tu agente si est\u00e1 abierto.`);
|
|
467
517
|
console.log(` \u2022 Ejecut\u00e1 el comando "forge" dentro del agente.`);
|
|
468
|
-
console.log(` \u2022
|
|
518
|
+
console.log(` \u2022 forgeSentinel se activa autom\u00e1ticamente tras cada escritura.`);
|
|
519
|
+
console.log(` \u2022 forgeSmith (Cursor) previene escrituras con violaciones CRITICAL.`);
|
|
520
|
+
console.log(` \u2022 Gesti\u00f3n de hooks: node .<agent>/skills/forge/scripts/forgeSmith-admin.mjs`);
|
|
469
521
|
console.log();
|
|
470
522
|
console.log(" " + SEP);
|
|
471
523
|
console.log();
|