@dedesfr/prompter 0.8.23 → 0.9.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/CHANGELOG.md +49 -0
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -7
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +32 -294
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +17 -40
- package/dist/commands/update.js.map +1 -1
- package/dist/core/configurators/slash/antigravity.d.ts +2 -5
- package/dist/core/configurators/slash/antigravity.d.ts.map +1 -1
- package/dist/core/configurators/slash/antigravity.js +2 -57
- package/dist/core/configurators/slash/antigravity.js.map +1 -1
- package/dist/core/configurators/slash/base.d.ts +6 -18
- package/dist/core/configurators/slash/base.d.ts.map +1 -1
- package/dist/core/configurators/slash/base.js +8 -77
- package/dist/core/configurators/slash/base.js.map +1 -1
- package/dist/core/configurators/slash/claude.d.ts +2 -5
- package/dist/core/configurators/slash/claude.d.ts.map +1 -1
- package/dist/core/configurators/slash/claude.js +2 -57
- package/dist/core/configurators/slash/claude.js.map +1 -1
- package/dist/core/configurators/slash/codex.d.ts +2 -5
- package/dist/core/configurators/slash/codex.d.ts.map +1 -1
- package/dist/core/configurators/slash/codex.js +2 -57
- package/dist/core/configurators/slash/codex.js.map +1 -1
- package/dist/core/configurators/slash/droid.d.ts +2 -5
- package/dist/core/configurators/slash/droid.d.ts.map +1 -1
- package/dist/core/configurators/slash/droid.js +2 -32
- package/dist/core/configurators/slash/droid.js.map +1 -1
- package/dist/core/configurators/slash/forge.d.ts +2 -5
- package/dist/core/configurators/slash/forge.d.ts.map +1 -1
- package/dist/core/configurators/slash/forge.js +2 -32
- package/dist/core/configurators/slash/forge.js.map +1 -1
- package/dist/core/configurators/slash/github-copilot.d.ts +2 -7
- package/dist/core/configurators/slash/github-copilot.d.ts.map +1 -1
- package/dist/core/configurators/slash/github-copilot.js +2 -96
- package/dist/core/configurators/slash/github-copilot.js.map +1 -1
- package/dist/core/configurators/slash/index.d.ts +1 -1
- package/dist/core/configurators/slash/index.d.ts.map +1 -1
- package/dist/core/configurators/slash/index.js +1 -1
- package/dist/core/configurators/slash/index.js.map +1 -1
- package/dist/core/configurators/slash/kilocode.d.ts +2 -5
- package/dist/core/configurators/slash/kilocode.d.ts.map +1 -1
- package/dist/core/configurators/slash/kilocode.js +2 -57
- package/dist/core/configurators/slash/kilocode.js.map +1 -1
- package/dist/core/configurators/slash/opencode.d.ts +2 -5
- package/dist/core/configurators/slash/opencode.d.ts.map +1 -1
- package/dist/core/configurators/slash/opencode.js +2 -57
- package/dist/core/configurators/slash/opencode.js.map +1 -1
- package/dist/core/configurators/slash/registry.d.ts +4 -4
- package/dist/core/configurators/slash/registry.d.ts.map +1 -1
- package/dist/core/configurators/slash/registry.js.map +1 -1
- package/dist/core/templates/index.d.ts +0 -1
- package/dist/core/templates/index.d.ts.map +1 -1
- package/dist/core/templates/index.js +0 -1
- package/dist/core/templates/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/ai-humanizer/SKILL.md +50 -0
- package/skills/api-contract-generator/SKILL.md +243 -0
- package/skills/apply/SKILL.md +23 -0
- package/skills/archive/SKILL.md +27 -0
- package/skills/design-system/SKILL.md +216 -0
- package/skills/document-explainer/SKILL.md +155 -0
- package/skills/enhance/SKILL.md +47 -0
- package/skills/epic-generator/SKILL.md +204 -0
- package/skills/epic-single/SKILL.md +63 -0
- package/skills/erd-generator/SKILL.md +138 -0
- package/skills/fsd-generator/SKILL.md +163 -0
- package/skills/prd-agent-generator/SKILL.md +132 -0
- package/skills/prd-generator/SKILL.md +211 -0
- package/skills/product-brief/SKILL.md +141 -0
- package/skills/proposal/SKILL.md +28 -0
- package/skills/qa-test-scenario/SKILL.md +149 -0
- package/skills/skill-creator/SKILL.md +173 -0
- package/skills/story-generator/SKILL.md +285 -0
- package/skills/story-single/SKILL.md +86 -0
- package/skills/tdd-generator/SKILL.md +300 -0
- package/skills/tdd-lite-generator/SKILL.md +230 -0
- package/skills/wireframe-generator/SKILL.md +227 -0
- package/src/cli/index.ts +1 -1
- package/src/commands/init.ts +32 -334
- package/src/commands/update.ts +20 -47
- package/src/core/configurators/slash/antigravity.ts +2 -62
- package/src/core/configurators/slash/base.ts +11 -105
- package/src/core/configurators/slash/claude.ts +2 -62
- package/src/core/configurators/slash/codex.ts +2 -62
- package/src/core/configurators/slash/droid.ts +2 -36
- package/src/core/configurators/slash/forge.ts +2 -36
- package/src/core/configurators/slash/github-copilot.ts +2 -106
- package/src/core/configurators/slash/index.ts +1 -1
- package/src/core/configurators/slash/kilocode.ts +2 -62
- package/src/core/configurators/slash/opencode.ts +2 -62
- package/src/core/configurators/slash/registry.ts +5 -5
- package/src/core/templates/index.ts +0 -1
- package/dist/core/templates/slash-command-templates.d.ts +0 -7
- package/dist/core/templates/slash-command-templates.d.ts.map +0 -1
- package/dist/core/templates/slash-command-templates.js +0 -1041
- package/dist/core/templates/slash-command-templates.js.map +0 -1
- package/src/core/templates/slash-command-templates.ts +0 -1068
package/src/commands/init.ts
CHANGED
|
@@ -3,94 +3,59 @@ import path from 'path';
|
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { checkbox, Separator } from '@inquirer/prompts';
|
|
6
|
-
import { PROMPTER_DIR, SUPPORTED_TOOLS,
|
|
6
|
+
import { PROMPTER_DIR, SUPPORTED_TOOLS, PrompterConfig } from '../core/config.js';
|
|
7
7
|
import { projectTemplate, agentsTemplate, claudeTemplate } from '../core/templates/index.js';
|
|
8
|
-
import { PROMPT_TEMPLATES } from '../core/prompt-templates.js';
|
|
9
8
|
import { registry } from '../core/configurators/slash/index.js';
|
|
10
|
-
import { SlashCommandId } from '../core/templates/index.js';
|
|
11
9
|
import { discoverSkills, SkillMetadata } from '../core/skill-discovery.js';
|
|
12
10
|
|
|
13
11
|
interface InitOptions {
|
|
14
12
|
tools?: string[];
|
|
15
|
-
prompts?: string[];
|
|
16
13
|
skills?: string[];
|
|
17
14
|
noInteractive?: boolean;
|
|
18
15
|
}
|
|
19
16
|
|
|
20
17
|
export class InitCommand {
|
|
21
|
-
private
|
|
18
|
+
private truncateDescription(desc: string, max = 72): string {
|
|
19
|
+
return desc.length > max ? desc.slice(0, max - 1) + '…' : desc;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private getCategorizedSkillChoices(availableSkills: SkillMetadata[], currentSkillNames: string[]): any[] {
|
|
22
23
|
const categories = [
|
|
23
24
|
{
|
|
24
|
-
name: '📋
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: '📐 Specification & Documentation',
|
|
29
|
-
prompts: ['fsd-generator', 'tdd-generator', 'tdd-lite-generator', 'erd-generator', 'api-contract-generator']
|
|
25
|
+
name: '📋 Planning & Strategy',
|
|
26
|
+
skills: ['project-orchestrator', 'feature-planner', 'prd-generator', 'prd-agent-generator', 'product-brief']
|
|
30
27
|
},
|
|
31
28
|
{
|
|
32
|
-
name: '🎯 Agile &
|
|
33
|
-
|
|
29
|
+
name: '🎯 Agile & Backlog',
|
|
30
|
+
skills: ['epic-single', 'epic-generator', 'story-single', 'story-generator']
|
|
34
31
|
},
|
|
35
32
|
{
|
|
36
|
-
name: '
|
|
37
|
-
|
|
33
|
+
name: '📐 Specification & Architecture',
|
|
34
|
+
skills: ['fsd-generator', 'tdd-generator', 'tdd-lite-generator', 'erd-generator', 'api-contract-generator']
|
|
38
35
|
},
|
|
39
36
|
{
|
|
40
37
|
name: '🎨 Design & UI/UX',
|
|
41
|
-
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
name: '⚙️ Development Workflow',
|
|
45
|
-
prompts: ['proposal', 'apply', 'archive']
|
|
38
|
+
skills: ['ui-ux-pro', 'design-system-generator', 'design-system', 'wireframe-generator', 'design-md', 'frontend-design']
|
|
46
39
|
},
|
|
47
40
|
{
|
|
48
|
-
name: '
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
const choices: any[] = [];
|
|
54
|
-
|
|
55
|
-
for (const category of categories) {
|
|
56
|
-
choices.push(new Separator(chalk.bold.cyan(category.name)));
|
|
57
|
-
|
|
58
|
-
for (const promptValue of category.prompts) {
|
|
59
|
-
const prompt = AVAILABLE_PROMPTS.find(p => p.value === promptValue);
|
|
60
|
-
if (prompt) {
|
|
61
|
-
choices.push({
|
|
62
|
-
name: ` ${prompt.name} ${chalk.gray('- ' + prompt.description)}`,
|
|
63
|
-
value: prompt.value,
|
|
64
|
-
checked: currentPrompts.includes(prompt.value)
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return choices;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private getCategorizedSkillChoices(availableSkills: SkillMetadata[], currentSkillNames: string[]): any[] {
|
|
74
|
-
const categories = [
|
|
75
|
-
{
|
|
76
|
-
name: '📋 Planning & Strategy',
|
|
77
|
-
skills: ['project-orchestrator', 'feature-planner', 'prompter-workflow', 'prompter-specs']
|
|
41
|
+
name: '⚙️ Development & Code Review',
|
|
42
|
+
skills: ['code-review', 'laravel-code-review', 'mcp-builder', 'skill-creator']
|
|
78
43
|
},
|
|
79
44
|
{
|
|
80
|
-
name: '
|
|
81
|
-
skills: ['
|
|
45
|
+
name: '✅ Testing & QA',
|
|
46
|
+
skills: ['qa-test-scenario']
|
|
82
47
|
},
|
|
83
48
|
{
|
|
84
|
-
name: '
|
|
85
|
-
skills: ['
|
|
49
|
+
name: '⚡ Prompter Workflow',
|
|
50
|
+
skills: ['prompter-workflow', 'prompter-specs', 'proposal', 'apply', 'archive']
|
|
86
51
|
},
|
|
87
52
|
{
|
|
88
53
|
name: '📝 Documentation',
|
|
89
|
-
skills: ['doc-builder', 'document-translator', 'ai-context-generator', 'meeting-notes', 'sph-generator']
|
|
54
|
+
skills: ['doc-builder', 'document-translator', 'document-explainer', 'ai-context-generator', 'meeting-notes', 'sph-generator']
|
|
90
55
|
},
|
|
91
56
|
{
|
|
92
57
|
name: '✨ Content & Productivity',
|
|
93
|
-
skills: ['
|
|
58
|
+
skills: ['enhance', 'enhance-prompt', 'ai-humanizer', 'gamma-builder', 'cerebro']
|
|
94
59
|
}
|
|
95
60
|
];
|
|
96
61
|
|
|
@@ -108,7 +73,7 @@ export class InitCommand {
|
|
|
108
73
|
for (const skill of skillsInCategory) {
|
|
109
74
|
categorized.add(skill.name);
|
|
110
75
|
choices.push({
|
|
111
|
-
name: ` ${skill.name}`,
|
|
76
|
+
name: ` ${skill.name} ${chalk.gray('- ' + this.truncateDescription(skill.description))}`,
|
|
112
77
|
value: skill.name,
|
|
113
78
|
checked: currentSkillNames.includes(skill.name)
|
|
114
79
|
});
|
|
@@ -121,7 +86,7 @@ export class InitCommand {
|
|
|
121
86
|
choices.push(new Separator(chalk.bold.cyan('🔧 Other')));
|
|
122
87
|
for (const skill of uncategorized) {
|
|
123
88
|
choices.push({
|
|
124
|
-
name: ` ${skill.name}`,
|
|
89
|
+
name: ` ${skill.name} ${chalk.gray('- ' + this.truncateDescription(skill.description))}`,
|
|
125
90
|
value: skill.name,
|
|
126
91
|
checked: currentSkillNames.includes(skill.name)
|
|
127
92
|
});
|
|
@@ -198,30 +163,6 @@ export class InitCommand {
|
|
|
198
163
|
selectedTools = currentTools;
|
|
199
164
|
}
|
|
200
165
|
|
|
201
|
-
// Select prompts
|
|
202
|
-
let selectedPrompts: string[] = [];
|
|
203
|
-
|
|
204
|
-
if (options.prompts && options.prompts.length > 0) {
|
|
205
|
-
// Handle comma-separated values in a single string or array of strings
|
|
206
|
-
selectedPrompts = options.prompts.flatMap(prompt => prompt.split(',').map(p => p.trim()));
|
|
207
|
-
} else if (!options.noInteractive) {
|
|
208
|
-
try {
|
|
209
|
-
// Detect currently installed prompts (use path.join to get prompter path)
|
|
210
|
-
const prompterPathForDetection = path.join(projectPath, PROMPTER_DIR);
|
|
211
|
-
const currentPrompts = await this.detectInstalledPrompts(prompterPathForDetection);
|
|
212
|
-
|
|
213
|
-
selectedPrompts = await checkbox({
|
|
214
|
-
message: 'Select prompt templates to install:',
|
|
215
|
-
choices: this.getCategorizedPromptChoices(currentPrompts),
|
|
216
|
-
pageSize: 20
|
|
217
|
-
});
|
|
218
|
-
} catch (error) {
|
|
219
|
-
// User cancelled
|
|
220
|
-
console.log(chalk.yellow(isReInitialization ? '\nRe-configuration cancelled.' : '\nInitialization cancelled.'));
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
166
|
// Select skills — resolve from the package directory, not the user's project
|
|
226
167
|
// dist/commands/init.js → go up two levels to reach the package root
|
|
227
168
|
const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
@@ -317,13 +258,6 @@ export class InitCommand {
|
|
|
317
258
|
const toolsToRemove = currentTools.filter(t => !selectedTools.includes(t));
|
|
318
259
|
const toolsToKeep = selectedTools.filter(t => currentTools.includes(t));
|
|
319
260
|
|
|
320
|
-
// Handle prompt changes
|
|
321
|
-
const prompterPathForDetection = path.join(projectPath, PROMPTER_DIR);
|
|
322
|
-
const currentPrompts = await this.detectInstalledPrompts(prompterPathForDetection);
|
|
323
|
-
const promptsToAdd = selectedPrompts.filter(p => !currentPrompts.includes(p));
|
|
324
|
-
const promptsToRemove = currentPrompts.filter(p => !selectedPrompts.includes(p));
|
|
325
|
-
const promptsToKeep = selectedPrompts.filter(p => currentPrompts.includes(p));
|
|
326
|
-
|
|
327
261
|
// Remove old tool files
|
|
328
262
|
if (toolsToRemove.length > 0) {
|
|
329
263
|
console.log(chalk.blue('\n🗑️ Removing workflow files...\n'));
|
|
@@ -342,75 +276,6 @@ export class InitCommand {
|
|
|
342
276
|
}
|
|
343
277
|
}
|
|
344
278
|
|
|
345
|
-
// Remove unchecked prompts
|
|
346
|
-
if (promptsToRemove.length > 0) {
|
|
347
|
-
console.log(chalk.blue('\n🗑️ Removing prompt templates...\n'));
|
|
348
|
-
|
|
349
|
-
// Remove from prompter/ folder
|
|
350
|
-
const removedPrompts = await this.removePrompts(prompterPath, promptsToRemove);
|
|
351
|
-
for (const promptName of removedPrompts) {
|
|
352
|
-
console.log(chalk.yellow('✓') + ` Removed ${chalk.cyan(promptName)}`);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// Remove workflow files from all configured tools
|
|
356
|
-
await this.removeWorkflowFilesForPrompts(projectPath, currentTools, promptsToRemove);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// Generate workflow files for new tools
|
|
360
|
-
if (toolsToAdd.length > 0) {
|
|
361
|
-
console.log(chalk.blue('\n📝 Creating workflow files...\n'));
|
|
362
|
-
|
|
363
|
-
// Convert selected prompt values to SlashCommandIds
|
|
364
|
-
const slashCommandIds: SlashCommandId[] = selectedPrompts as SlashCommandId[];
|
|
365
|
-
|
|
366
|
-
for (const toolId of toolsToAdd) {
|
|
367
|
-
const configurator = registry.get(toolId);
|
|
368
|
-
if (configurator) {
|
|
369
|
-
try {
|
|
370
|
-
// Pass selected prompts to only generate those workflow files
|
|
371
|
-
// Pass empty array if no prompts selected to generate nothing
|
|
372
|
-
const files = await configurator.generateAll(projectPath, slashCommandIds);
|
|
373
|
-
for (const file of files) {
|
|
374
|
-
console.log(chalk.green('✓') + ` Created ${chalk.cyan(file)}`);
|
|
375
|
-
}
|
|
376
|
-
} catch (error) {
|
|
377
|
-
console.log(chalk.red('✗') + ` Failed to create files for ${toolId}: ${error}`);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Add missing workflow files for existing tools
|
|
384
|
-
if (isReInitialization && toolsToKeep.length > 0) {
|
|
385
|
-
const missingFiles: string[] = [];
|
|
386
|
-
|
|
387
|
-
// Convert selected prompt values to SlashCommandIds
|
|
388
|
-
const slashCommandIds: SlashCommandId[] = selectedPrompts as SlashCommandId[];
|
|
389
|
-
|
|
390
|
-
for (const toolId of toolsToKeep) {
|
|
391
|
-
const configurator = registry.get(toolId);
|
|
392
|
-
if (configurator) {
|
|
393
|
-
try {
|
|
394
|
-
// Pass selected prompts to only generate those workflow files
|
|
395
|
-
// Pass empty array if no prompts selected to generate nothing
|
|
396
|
-
const files = await configurator.generateAll(projectPath, slashCommandIds);
|
|
397
|
-
for (const file of files) {
|
|
398
|
-
missingFiles.push(file);
|
|
399
|
-
}
|
|
400
|
-
} catch (error) {
|
|
401
|
-
// Ignore errors for kept tools
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
if (missingFiles.length > 0) {
|
|
407
|
-
console.log(chalk.blue('\n📝 Adding missing workflow files...\n'));
|
|
408
|
-
for (const file of missingFiles) {
|
|
409
|
-
console.log(chalk.green('✓') + ` Created ${chalk.cyan(file)}`);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
279
|
// Show kept tools
|
|
415
280
|
if (isReInitialization && toolsToKeep.length > 0 && (toolsToAdd.length > 0 || toolsToRemove.length > 0)) {
|
|
416
281
|
console.log(chalk.blue('\n✨ Keeping existing tools:\n'));
|
|
@@ -422,31 +287,13 @@ export class InitCommand {
|
|
|
422
287
|
}
|
|
423
288
|
}
|
|
424
289
|
|
|
425
|
-
// Install new prompts
|
|
426
|
-
if (promptsToAdd.length > 0) {
|
|
427
|
-
console.log(chalk.blue('\n📋 Installing prompt templates...\n'));
|
|
428
|
-
const installedPrompts = await this.installPrompts(projectPath, prompterPath, promptsToAdd);
|
|
429
|
-
for (const promptName of installedPrompts) {
|
|
430
|
-
console.log(chalk.green('✓') + ` Installed ${chalk.cyan(promptName)}`);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// Update existing prompts in prompter/core/
|
|
435
|
-
if (isReInitialization && promptsToKeep.length > 0) {
|
|
436
|
-
console.log(chalk.blue('\n🔄 Updating existing prompt templates...\n'));
|
|
437
|
-
const updatedPrompts = await this.installPrompts(projectPath, prompterPath, promptsToKeep);
|
|
438
|
-
for (const promptName of updatedPrompts) {
|
|
439
|
-
console.log(chalk.green('✓') + ` Updated ${chalk.cyan(promptName)}`);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
290
|
// --- Skills setup ---
|
|
444
291
|
const skillChanges = await this.setupSkills(projectPath, prompterPath, selectedTools, selectedSkills);
|
|
445
292
|
|
|
446
293
|
// Success message
|
|
447
294
|
if (isReInitialization) {
|
|
448
295
|
console.log(chalk.green('\n✅ Prompter tools updated successfully!\n'));
|
|
449
|
-
if (toolsToAdd.length > 0 || toolsToRemove.length > 0 ||
|
|
296
|
+
if (toolsToAdd.length > 0 || toolsToRemove.length > 0 || skillChanges.added.length > 0 || skillChanges.removed.length > 0) {
|
|
450
297
|
console.log(chalk.blue('Summary:'));
|
|
451
298
|
if (toolsToAdd.length > 0) {
|
|
452
299
|
console.log(chalk.green(' Tools Added: ') + toolsToAdd.map(t => {
|
|
@@ -460,18 +307,6 @@ export class InitCommand {
|
|
|
460
307
|
return tool ? tool.name : t;
|
|
461
308
|
}).join(', '));
|
|
462
309
|
}
|
|
463
|
-
if (promptsToAdd.length > 0) {
|
|
464
|
-
console.log(chalk.green(' Prompts Added: ') + promptsToAdd.map(p => {
|
|
465
|
-
const prompt = AVAILABLE_PROMPTS.find(ap => ap.value === p);
|
|
466
|
-
return prompt ? prompt.name : p;
|
|
467
|
-
}).join(', '));
|
|
468
|
-
}
|
|
469
|
-
if (promptsToRemove.length > 0) {
|
|
470
|
-
console.log(chalk.yellow(' Prompts Removed: ') + promptsToRemove.map(p => {
|
|
471
|
-
const prompt = AVAILABLE_PROMPTS.find(ap => ap.value === p);
|
|
472
|
-
return prompt ? prompt.name : p;
|
|
473
|
-
}).join(', '));
|
|
474
|
-
}
|
|
475
310
|
if (skillChanges.added.length > 0) {
|
|
476
311
|
console.log(chalk.green(' Skills Added: ') + skillChanges.added.join(', '));
|
|
477
312
|
}
|
|
@@ -484,9 +319,6 @@ export class InitCommand {
|
|
|
484
319
|
}
|
|
485
320
|
} else {
|
|
486
321
|
console.log(chalk.green('\n✅ Prompter initialized successfully!\n'));
|
|
487
|
-
if (promptsToAdd.length > 0) {
|
|
488
|
-
console.log(chalk.gray(`Installed ${promptsToAdd.length} prompt template(s).\n`));
|
|
489
|
-
}
|
|
490
322
|
if (skillChanges.added.length > 0) {
|
|
491
323
|
console.log(chalk.gray(`Installed ${skillChanges.added.length} skill(s).\n`));
|
|
492
324
|
}
|
|
@@ -508,19 +340,12 @@ export class InitCommand {
|
|
|
508
340
|
const allConfigurators = registry.getAll();
|
|
509
341
|
|
|
510
342
|
for (const configurator of allConfigurators) {
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
hasFiles = true;
|
|
518
|
-
break;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
if (hasFiles) {
|
|
523
|
-
configuredTools.push(configurator.toolId);
|
|
343
|
+
const skillsRoot = path.join(projectPath, configurator.getSkillsRootDir());
|
|
344
|
+
try {
|
|
345
|
+
const stat = await fs.stat(skillsRoot);
|
|
346
|
+
if (stat.isDirectory()) configuredTools.push(configurator.toolId);
|
|
347
|
+
} catch {
|
|
348
|
+
// directory doesn't exist — tool not configured
|
|
524
349
|
}
|
|
525
350
|
}
|
|
526
351
|
|
|
@@ -528,138 +353,11 @@ export class InitCommand {
|
|
|
528
353
|
}
|
|
529
354
|
|
|
530
355
|
private async removeToolFiles(projectPath: string, configurator: any): Promise<string[]> {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
for (const target of targets) {
|
|
535
|
-
const filePath = path.join(projectPath, target.path);
|
|
536
|
-
if (await this.fileExists(filePath)) {
|
|
537
|
-
await fs.unlink(filePath);
|
|
538
|
-
removedFiles.push(target.path);
|
|
539
|
-
|
|
540
|
-
// Remove empty parent directories
|
|
541
|
-
await this.removeEmptyDirs(path.dirname(filePath), projectPath);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
return removedFiles;
|
|
356
|
+
await configurator.removeAllDeployedSkills(projectPath);
|
|
357
|
+
return [configurator.getSkillsRootDir() + '/'];
|
|
546
358
|
}
|
|
547
359
|
|
|
548
|
-
private async removeEmptyDirs(dirPath: string, projectPath: string): Promise<void> {
|
|
549
|
-
// Don't remove the project directory itself
|
|
550
|
-
if (dirPath === projectPath || dirPath === path.dirname(projectPath)) {
|
|
551
|
-
return;
|
|
552
|
-
}
|
|
553
360
|
|
|
554
|
-
try {
|
|
555
|
-
const files = await fs.readdir(dirPath);
|
|
556
|
-
if (files.length === 0) {
|
|
557
|
-
await fs.rmdir(dirPath);
|
|
558
|
-
// Recursively check parent
|
|
559
|
-
await this.removeEmptyDirs(path.dirname(dirPath), projectPath);
|
|
560
|
-
}
|
|
561
|
-
} catch {
|
|
562
|
-
// Directory doesn't exist or can't be removed, ignore
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
private async detectInstalledPrompts(prompterPath: string): Promise<string[]> {
|
|
567
|
-
const installedPrompts: string[] = [];
|
|
568
|
-
const corePath = path.join(prompterPath, 'core');
|
|
569
|
-
|
|
570
|
-
for (const prompt of AVAILABLE_PROMPTS) {
|
|
571
|
-
const promptFilePath = path.join(corePath, prompt.sourceFile);
|
|
572
|
-
if (await this.fileExists(promptFilePath)) {
|
|
573
|
-
installedPrompts.push(prompt.value);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
return installedPrompts;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
private async installPrompts(projectPath: string, prompterPath: string, selectedPrompts: string[]): Promise<string[]> {
|
|
581
|
-
const installedPrompts: string[] = [];
|
|
582
|
-
const corePath = path.join(prompterPath, 'core');
|
|
583
|
-
|
|
584
|
-
// Ensure core directory exists
|
|
585
|
-
await fs.mkdir(corePath, { recursive: true });
|
|
586
|
-
|
|
587
|
-
for (const promptId of selectedPrompts) {
|
|
588
|
-
const prompt = AVAILABLE_PROMPTS.find(p => p.value === promptId);
|
|
589
|
-
if (!prompt) continue;
|
|
590
|
-
|
|
591
|
-
const destPath = path.join(corePath, prompt.sourceFile);
|
|
592
|
-
|
|
593
|
-
try {
|
|
594
|
-
// Get template content from embedded templates
|
|
595
|
-
const content = PROMPT_TEMPLATES[promptId];
|
|
596
|
-
|
|
597
|
-
if (!content) {
|
|
598
|
-
console.log(chalk.yellow(` Warning: Template not found for ${prompt.name}`));
|
|
599
|
-
continue;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
// Write the prompt file from embedded template (overwrites if exists)
|
|
603
|
-
await fs.writeFile(destPath, content, 'utf-8');
|
|
604
|
-
installedPrompts.push(prompt.name);
|
|
605
|
-
} catch (error) {
|
|
606
|
-
console.log(chalk.red(` Error installing ${prompt.name}: ${error}`));
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
return installedPrompts;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
private async removePrompts(prompterPath: string, promptsToRemove: string[]): Promise<string[]> {
|
|
614
|
-
const removedPrompts: string[] = [];
|
|
615
|
-
const corePath = path.join(prompterPath, 'core');
|
|
616
|
-
|
|
617
|
-
for (const promptId of promptsToRemove) {
|
|
618
|
-
const prompt = AVAILABLE_PROMPTS.find(p => p.value === promptId);
|
|
619
|
-
if (!prompt) continue;
|
|
620
|
-
|
|
621
|
-
const filePath = path.join(corePath, prompt.sourceFile);
|
|
622
|
-
|
|
623
|
-
try {
|
|
624
|
-
if (await this.fileExists(filePath)) {
|
|
625
|
-
await fs.unlink(filePath);
|
|
626
|
-
removedPrompts.push(prompt.name);
|
|
627
|
-
}
|
|
628
|
-
} catch (error) {
|
|
629
|
-
console.log(chalk.red(` Error removing ${prompt.name}: ${error}`));
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
return removedPrompts;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
private async removeWorkflowFilesForPrompts(projectPath: string, toolIds: string[], promptIds: string[]): Promise<void> {
|
|
637
|
-
const slashCommandIds: SlashCommandId[] = promptIds as SlashCommandId[];
|
|
638
|
-
|
|
639
|
-
for (const toolId of toolIds) {
|
|
640
|
-
const configurator = registry.get(toolId);
|
|
641
|
-
if (!configurator) continue;
|
|
642
|
-
|
|
643
|
-
// Get targets for the prompts to remove
|
|
644
|
-
const targets = configurator.getTargets(slashCommandIds);
|
|
645
|
-
|
|
646
|
-
for (const target of targets) {
|
|
647
|
-
const filePath = path.join(projectPath, target.path);
|
|
648
|
-
|
|
649
|
-
try {
|
|
650
|
-
if (await this.fileExists(filePath)) {
|
|
651
|
-
await fs.unlink(filePath);
|
|
652
|
-
console.log(chalk.yellow('✓') + ` Removed ${chalk.cyan(target.path)}`);
|
|
653
|
-
|
|
654
|
-
// Remove empty parent directories
|
|
655
|
-
await this.removeEmptyDirs(path.dirname(filePath), projectPath);
|
|
656
|
-
}
|
|
657
|
-
} catch (error) {
|
|
658
|
-
// Silently ignore errors for workflow file removal
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
361
|
|
|
664
362
|
private async ensureRootClaudeFile(projectPath: string): Promise<void> {
|
|
665
363
|
const rootClaudePath = path.join(projectPath, 'CLAUDE.md');
|
package/src/commands/update.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { promises as fs } from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
4
5
|
import { PrompterConfig, AVAILABLE_PROMPTS, PROMPTER_DIR } from '../core/config.js';
|
|
5
6
|
import { registry } from '../core/configurators/slash/index.js';
|
|
6
7
|
import { PROMPT_TEMPLATES } from '../core/prompt-templates.js';
|
|
@@ -32,17 +33,21 @@ export class UpdateCommand {
|
|
|
32
33
|
|
|
33
34
|
let updatedCount = 0;
|
|
34
35
|
|
|
35
|
-
//
|
|
36
|
+
// Clean up legacy slash command files and update skills for each tool
|
|
37
|
+
const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
38
|
+
const availableSkills = await discoverSkills(path.join(packageDir, 'skills'));
|
|
39
|
+
|
|
36
40
|
for (const toolId of configuredTools) {
|
|
37
41
|
const configurator = registry.get(toolId);
|
|
38
42
|
if (!configurator) continue;
|
|
39
43
|
|
|
40
44
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
if (availableSkills.length > 0) {
|
|
46
|
+
const updatedSkillFiles = await configurator.updateExistingSkills(projectPath, availableSkills);
|
|
47
|
+
for (const file of updatedSkillFiles) {
|
|
48
|
+
console.log(chalk.green('✓') + ` Updated ${chalk.cyan(file)}`);
|
|
49
|
+
updatedCount++;
|
|
50
|
+
}
|
|
46
51
|
}
|
|
47
52
|
} catch (error) {
|
|
48
53
|
console.log(chalk.red('✗') + ` Failed to update ${configurator.toolId}: ${error}`);
|
|
@@ -57,27 +62,6 @@ export class UpdateCommand {
|
|
|
57
62
|
updatedCount++;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
// Update existing skill workflow files
|
|
61
|
-
const skillsDir = path.join(projectPath, 'skills');
|
|
62
|
-
const availableSkills = await discoverSkills(skillsDir);
|
|
63
|
-
|
|
64
|
-
if (availableSkills.length > 0) {
|
|
65
|
-
for (const toolId of configuredTools) {
|
|
66
|
-
const configurator = registry.get(toolId);
|
|
67
|
-
if (!configurator) continue;
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
const updatedSkillFiles = await configurator.updateExistingSkills(projectPath, availableSkills);
|
|
71
|
-
for (const file of updatedSkillFiles) {
|
|
72
|
-
console.log(chalk.green('✓') + ` Updated ${chalk.cyan(file)}`);
|
|
73
|
-
updatedCount++;
|
|
74
|
-
}
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.log(chalk.red('✗') + ` Failed to update skills for ${configurator.toolId}: ${error}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
65
|
if (updatedCount === 0) {
|
|
82
66
|
console.log(chalk.yellow('⚠️ No workflow files found to update.'));
|
|
83
67
|
console.log(chalk.gray(' Run `prompter init` to create them.\n'));
|
|
@@ -100,19 +84,12 @@ export class UpdateCommand {
|
|
|
100
84
|
const allConfigurators = registry.getAll();
|
|
101
85
|
|
|
102
86
|
for (const configurator of allConfigurators) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
hasFiles = true;
|
|
110
|
-
break;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (hasFiles) {
|
|
115
|
-
configuredTools.push(configurator.toolId);
|
|
87
|
+
const skillsRoot = path.join(projectPath, configurator.getSkillsRootDir());
|
|
88
|
+
try {
|
|
89
|
+
const stat = await fs.stat(skillsRoot);
|
|
90
|
+
if (stat.isDirectory()) configuredTools.push(configurator.toolId);
|
|
91
|
+
} catch {
|
|
92
|
+
// directory doesn't exist — tool not configured
|
|
116
93
|
}
|
|
117
94
|
}
|
|
118
95
|
|
|
@@ -123,26 +100,22 @@ export class UpdateCommand {
|
|
|
123
100
|
const updatedPrompts: string[] = [];
|
|
124
101
|
const corePath = path.join(prompterPath, 'core');
|
|
125
102
|
|
|
126
|
-
// Check if core directory exists
|
|
127
103
|
if (!await this.fileExists(corePath)) {
|
|
128
104
|
return updatedPrompts;
|
|
129
105
|
}
|
|
130
106
|
|
|
131
|
-
// Update each existing prompt file
|
|
132
107
|
for (const prompt of AVAILABLE_PROMPTS) {
|
|
133
108
|
const promptFilePath = path.join(corePath, prompt.sourceFile);
|
|
134
|
-
|
|
135
|
-
// Only update if file exists
|
|
109
|
+
|
|
136
110
|
if (await this.fileExists(promptFilePath)) {
|
|
137
111
|
try {
|
|
138
112
|
const content = PROMPT_TEMPLATES[prompt.value];
|
|
139
|
-
|
|
113
|
+
|
|
140
114
|
if (!content) {
|
|
141
115
|
console.log(chalk.yellow(` Warning: Template not found for ${prompt.name}`));
|
|
142
116
|
continue;
|
|
143
117
|
}
|
|
144
|
-
|
|
145
|
-
// Update the prompt file
|
|
118
|
+
|
|
146
119
|
await fs.writeFile(promptFilePath, content, 'utf-8');
|
|
147
120
|
updatedPrompts.push(prompt.sourceFile);
|
|
148
121
|
} catch (error) {
|
|
@@ -1,69 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { SlashCommandId } from '../../templates/index.js';
|
|
1
|
+
import { ToolConfigurator } from './base.js';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
enhance: '.agent/workflows/prompter-enhance.md',
|
|
6
|
-
'prd-generator': '.agent/workflows/prd-generator.md',
|
|
7
|
-
'prd-agent-generator': '.agent/workflows/prd-agent-generator.md',
|
|
8
|
-
'product-brief': '.agent/workflows/product-brief.md',
|
|
9
|
-
'epic-single': '.agent/workflows/epic-single.md',
|
|
10
|
-
'epic-generator': '.agent/workflows/epic-generator.md',
|
|
11
|
-
'story-single': '.agent/workflows/story-single.md',
|
|
12
|
-
'story-generator': '.agent/workflows/story-generator.md',
|
|
13
|
-
'qa-test-scenario': '.agent/workflows/qa-test-scenario.md',
|
|
14
|
-
'skill-creator': '.agent/workflows/skill-creator.md',
|
|
15
|
-
'ai-humanizer': '.agent/workflows/ai-humanizer.md',
|
|
16
|
-
'api-contract-generator': '.agent/workflows/api-contract-generator.md',
|
|
17
|
-
'apply': '.agent/workflows/apply.md',
|
|
18
|
-
'archive': '.agent/workflows/archive.md',
|
|
19
|
-
'design-system': '.agent/workflows/design-system.md',
|
|
20
|
-
'erd-generator': '.agent/workflows/erd-generator.md',
|
|
21
|
-
'fsd-generator': '.agent/workflows/fsd-generator.md',
|
|
22
|
-
'proposal': '.agent/workflows/proposal.md',
|
|
23
|
-
'tdd-generator': '.agent/workflows/tdd-generator.md',
|
|
24
|
-
'tdd-lite-generator': '.agent/workflows/tdd-lite-generator.md',
|
|
25
|
-
'wireframe-generator': '.agent/workflows/wireframe-generator.md',
|
|
26
|
-
'document-explainer': '.agent/workflows/document-explainer.md'
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const DESCRIPTIONS: Record<SlashCommandId, string> = {
|
|
30
|
-
enhance: 'Enhance a rough prompt into a professional specification',
|
|
31
|
-
'prd-generator': 'Generate a comprehensive Product Requirements Document (PRD)',
|
|
32
|
-
'prd-agent-generator': 'Generate a PRD with autonomous assumptions (non-interactive mode)',
|
|
33
|
-
'product-brief': 'Generate an executive-level product brief (1-page summary)',
|
|
34
|
-
'epic-single': 'Generate a single well-defined Jira Epic',
|
|
35
|
-
'epic-generator': 'Generate a comprehensive set of EPICs from documentation',
|
|
36
|
-
'story-single': 'Generate a single Jira User Story from requirements',
|
|
37
|
-
'story-generator': 'Generate comprehensive user stories from EPICs and FSD',
|
|
38
|
-
'qa-test-scenario': 'Generate focused QA test scenarios from PRD',
|
|
39
|
-
'skill-creator': 'Create a modular skill package that extends AI agent capabilities',
|
|
40
|
-
'ai-humanizer': 'Humanize and proofread AI-generated content for natural, publication-ready output',
|
|
41
|
-
'api-contract-generator': 'Generate OpenAPI specification from FSD and ERD',
|
|
42
|
-
'apply': 'Implement and apply an approved change proposal',
|
|
43
|
-
'archive': 'Archive a completed change and update specs',
|
|
44
|
-
'design-system': 'Generate comprehensive design system documentation for components and tokens',
|
|
45
|
-
'erd-generator': 'Generate Entity Relationship Diagram from FSD',
|
|
46
|
-
'fsd-generator': 'Generate Functional Specification Document from PRD',
|
|
47
|
-
'proposal': 'Create a new change proposal with spec deltas',
|
|
48
|
-
'tdd-generator': 'Generate comprehensive Technical Design Document',
|
|
49
|
-
'tdd-lite-generator': 'Generate lean Technical Design Document (TDD-Lite)',
|
|
50
|
-
'wireframe-generator': 'Generate UI/UX wireframes from technical specs',
|
|
51
|
-
'document-explainer': 'Analyze and explain complex documents into clear, actionable insights'
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export class AntigravityConfigurator extends SlashCommandConfigurator {
|
|
3
|
+
export class AntigravityConfigurator extends ToolConfigurator {
|
|
55
4
|
readonly toolId = 'antigravity';
|
|
56
5
|
readonly isAvailable = true;
|
|
57
6
|
|
|
58
|
-
protected getRelativePath(id: SlashCommandId): string {
|
|
59
|
-
return FILE_PATHS[id];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
protected getFrontmatter(id: SlashCommandId): string | undefined {
|
|
63
|
-
const description = DESCRIPTIONS[id];
|
|
64
|
-
return `---\ndescription: ${description}\n---`;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
7
|
protected getSkillTargetDir(skillName: string): string {
|
|
68
8
|
return `.agent/skills/${skillName}`;
|
|
69
9
|
}
|