@aicgen/aicgen 1.0.0-beta.1 ā 1.0.0-beta.2
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/.vs/ProjectSettings.json +2 -2
- package/.vs/VSWorkspaceState.json +15 -15
- package/.vs/aicgen.slnx/v18/DocumentLayout.json +53 -53
- package/assets/icon.svg +33 -33
- package/bun.lock +0 -43
- package/data/architecture/microservices/api-gateway.md +56 -56
- package/data/devops/observability.md +73 -73
- package/dist/index.js +9299 -9299
- package/package.json +2 -2
- package/.claude/agents/architecture-reviewer.md +0 -88
- package/.claude/agents/guideline-checker.md +0 -73
- package/.claude/agents/security-auditor.md +0 -108
- package/.claude/guidelines/api-design.md +0 -645
- package/.claude/guidelines/architecture.md +0 -2503
- package/.claude/guidelines/best-practices.md +0 -618
- package/.claude/guidelines/code-style.md +0 -304
- package/.claude/guidelines/design-patterns.md +0 -573
- package/.claude/guidelines/devops.md +0 -226
- package/.claude/guidelines/error-handling.md +0 -413
- package/.claude/guidelines/language.md +0 -782
- package/.claude/guidelines/performance.md +0 -706
- package/.claude/guidelines/security.md +0 -583
- package/.claude/guidelines/testing.md +0 -568
- package/.claude/settings.json +0 -98
- package/.claude/settings.local.json +0 -8
- package/.eslintrc.json +0 -28
- package/.github/workflows/release.yml +0 -180
- package/.github/workflows/test.yml +0 -81
- package/CONTRIBUTING.md +0 -821
- package/dist/commands/init.d.ts +0 -8
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -46
- package/dist/commands/init.js.map +0 -1
- package/dist/config/profiles.d.ts +0 -4
- package/dist/config/profiles.d.ts.map +0 -1
- package/dist/config/profiles.js +0 -30
- package/dist/config/profiles.js.map +0 -1
- package/dist/config/settings.d.ts +0 -7
- package/dist/config/settings.d.ts.map +0 -1
- package/dist/config/settings.js +0 -7
- package/dist/config/settings.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/models/guideline.d.ts +0 -15
- package/dist/models/guideline.d.ts.map +0 -1
- package/dist/models/guideline.js +0 -2
- package/dist/models/guideline.js.map +0 -1
- package/dist/models/preference.d.ts +0 -9
- package/dist/models/preference.d.ts.map +0 -1
- package/dist/models/preference.js +0 -2
- package/dist/models/preference.js.map +0 -1
- package/dist/models/profile.d.ts +0 -9
- package/dist/models/profile.d.ts.map +0 -1
- package/dist/models/profile.js +0 -2
- package/dist/models/profile.js.map +0 -1
- package/dist/models/project.d.ts +0 -13
- package/dist/models/project.d.ts.map +0 -1
- package/dist/models/project.js +0 -2
- package/dist/models/project.js.map +0 -1
- package/dist/services/ai/anthropic.d.ts +0 -7
- package/dist/services/ai/anthropic.d.ts.map +0 -1
- package/dist/services/ai/anthropic.js +0 -39
- package/dist/services/ai/anthropic.js.map +0 -1
- package/dist/services/generator.d.ts +0 -2
- package/dist/services/generator.d.ts.map +0 -1
- package/dist/services/generator.js +0 -4
- package/dist/services/generator.js.map +0 -1
- package/dist/services/learner.d.ts +0 -2
- package/dist/services/learner.d.ts.map +0 -1
- package/dist/services/learner.js +0 -4
- package/dist/services/learner.js.map +0 -1
- package/dist/services/scanner.d.ts +0 -3
- package/dist/services/scanner.d.ts.map +0 -1
- package/dist/services/scanner.js +0 -54
- package/dist/services/scanner.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -15
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -27
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/file.d.ts +0 -7
- package/dist/utils/file.d.ts.map +0 -1
- package/dist/utils/file.js +0 -32
- package/dist/utils/file.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -6
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -17
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/path.d.ts +0 -6
- package/dist/utils/path.d.ts.map +0 -1
- package/dist/utils/path.js +0 -14
- package/dist/utils/path.js.map +0 -1
- package/docs/planning/memory-lane.md +0 -83
- package/packaging/linux/aicgen.spec +0 -23
- package/packaging/linux/control +0 -9
- package/packaging/macos/scripts/postinstall +0 -12
- package/packaging/windows/setup.nsi +0 -92
- package/scripts/add-categories.ts +0 -87
- package/scripts/build-binary.ts +0 -46
- package/scripts/embed-data.ts +0 -105
- package/scripts/generate-version.ts +0 -150
- package/scripts/test-decompress.ts +0 -27
- package/scripts/test-extract.ts +0 -31
- package/src/__tests__/services/assistant-file-writer.test.ts +0 -400
- package/src/__tests__/services/guideline-loader.test.ts +0 -281
- package/src/__tests__/services/tarball-extraction.test.ts +0 -125
- package/src/commands/add-guideline.ts +0 -296
- package/src/commands/clear.ts +0 -61
- package/src/commands/guideline-selector.ts +0 -123
- package/src/commands/init.ts +0 -645
- package/src/commands/quick-add.ts +0 -586
- package/src/commands/remove-guideline.ts +0 -152
- package/src/commands/stats.ts +0 -49
- package/src/commands/update.ts +0 -240
- package/src/config.ts +0 -82
- package/src/embedded-data.ts +0 -1492
- package/src/index.ts +0 -67
- package/src/models/profile.ts +0 -24
- package/src/models/project.ts +0 -43
- package/src/services/assistant-file-writer.ts +0 -612
- package/src/services/config-generator.ts +0 -150
- package/src/services/config-manager.ts +0 -70
- package/src/services/data-source.ts +0 -248
- package/src/services/first-run-init.ts +0 -148
- package/src/services/guideline-loader.ts +0 -311
- package/src/services/hook-generator.ts +0 -178
- package/src/services/subagent-generator.ts +0 -310
- package/src/utils/banner.ts +0 -66
- package/src/utils/errors.ts +0 -27
- package/src/utils/file.ts +0 -67
- package/src/utils/formatting.ts +0 -172
- package/src/utils/logger.ts +0 -89
- package/src/utils/path.ts +0 -17
- package/src/utils/wizard-state.ts +0 -132
- package/tsconfig.json +0 -25
- /package/{CLAUDE.md ā claude.md} +0 -0
package/src/commands/init.ts
DELETED
|
@@ -1,645 +0,0 @@
|
|
|
1
|
-
import { select, confirm } from '@inquirer/prompts';
|
|
2
|
-
import ora from 'ora';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import { ConfigGenerator } from '../services/config-generator.js';
|
|
5
|
-
import { ProfileSelection, InstructionLevel, ArchitectureType, DatasourceType } from '../models/profile.js';
|
|
6
|
-
import { AIAssistant, Language, ProjectType } from '../models/project.js';
|
|
7
|
-
import { GuidelineLoader } from '../services/guideline-loader.js';
|
|
8
|
-
import { showBanner, showInstructions } from '../utils/banner.js';
|
|
9
|
-
import { WizardStateManager, BACK_VALUE, addBackOption } from '../utils/wizard-state.js';
|
|
10
|
-
import { createSummaryBox, createMetricsBox } from '../utils/formatting.js';
|
|
11
|
-
import { selectGuidelines } from './guideline-selector.js';
|
|
12
|
-
import { CONFIG, GITHUB_RELEASES_URL } from '../config.js';
|
|
13
|
-
import { ensureDataInitialized } from '../services/first-run-init.js';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
interface InitOptions {
|
|
17
|
-
assistant?: string;
|
|
18
|
-
level?: string;
|
|
19
|
-
architecture?: string;
|
|
20
|
-
force?: boolean;
|
|
21
|
-
dryRun?: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const LANGUAGES: { value: Language; name: string }[] = [
|
|
25
|
-
{ value: 'typescript', name: 'TypeScript' },
|
|
26
|
-
{ value: 'javascript', name: 'JavaScript' },
|
|
27
|
-
{ value: 'python', name: 'Python' },
|
|
28
|
-
{ value: 'go', name: 'Go' },
|
|
29
|
-
{ value: 'rust', name: 'Rust' },
|
|
30
|
-
{ value: 'java', name: 'Java' },
|
|
31
|
-
{ value: 'csharp', name: 'C#' },
|
|
32
|
-
{ value: 'ruby', name: 'Ruby' }
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
const PROJECT_TYPES: { value: ProjectType; name: string; description: string }[] = [
|
|
36
|
-
{ value: 'web', name: 'Web Application', description: 'Frontend or full-stack web app' },
|
|
37
|
-
{ value: 'api', name: 'API / Backend', description: 'REST API, GraphQL, or backend service' },
|
|
38
|
-
{ value: 'cli', name: 'CLI Tool', description: 'Command-line application' },
|
|
39
|
-
{ value: 'library', name: 'Library / Package', description: 'Reusable library or npm/pip package' },
|
|
40
|
-
{ value: 'desktop', name: 'Desktop Application', description: 'Electron, Tauri, or native desktop app' },
|
|
41
|
-
{ value: 'mobile', name: 'Mobile Application', description: 'React Native, Flutter, or native mobile' },
|
|
42
|
-
{ value: 'other', name: 'Other', description: 'Something else' }
|
|
43
|
-
];
|
|
44
|
-
|
|
45
|
-
const ASSISTANTS: { value: AIAssistant; name: string; description: string }[] = [
|
|
46
|
-
{ value: 'claude-code', name: 'Claude Code', description: 'Anthropic\'s Claude for coding' },
|
|
47
|
-
{ value: 'copilot', name: 'GitHub Copilot', description: 'GitHub\'s AI pair programmer' },
|
|
48
|
-
{ value: 'gemini', name: 'Google Gemini', description: 'Google\'s AI model' },
|
|
49
|
-
{ value: 'antigravity', name: 'Google Antigravity', description: 'Google\'s agentic platform' },
|
|
50
|
-
{ value: 'codex', name: 'OpenAI Codex', description: 'OpenAI\'s code model' }
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
const ARCHITECTURES: { value: ArchitectureType; name: string; description: string }[] = [
|
|
54
|
-
{ value: 'layered', name: 'Layered', description: 'Simple layers: UI ā Business ā Data' },
|
|
55
|
-
{ value: 'modular-monolith', name: 'Modular Monolith', description: 'Single deploy with clear module boundaries' },
|
|
56
|
-
{ value: 'microservices', name: 'Microservices', description: 'Independent services with separate deploys' },
|
|
57
|
-
{ value: 'event-driven', name: 'Event-Driven', description: 'Event sourcing, CQRS, message queues' },
|
|
58
|
-
{ value: 'hexagonal', name: 'Hexagonal (Ports & Adapters)', description: 'Business logic isolated from infrastructure' },
|
|
59
|
-
{ value: 'clean-architecture', name: 'Clean Architecture', description: 'Uncle Bob\'s concentric layers with dependency rule' },
|
|
60
|
-
{ value: 'ddd', name: 'Domain-Driven Design', description: 'Bounded contexts, aggregates, domain events' },
|
|
61
|
-
{ value: 'serverless', name: 'Serverless', description: 'FaaS, event triggers, managed services' },
|
|
62
|
-
{ value: 'other', name: 'Other / None', description: 'Scripts, APIs, frontends, or no specific architecture' }
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
const DATASOURCES: { value: DatasourceType; name: string; description: string }[] = [
|
|
66
|
-
{ value: 'sql', name: 'SQL Database', description: 'PostgreSQL, MySQL, SQLite, etc.' },
|
|
67
|
-
{ value: 'nosql', name: 'NoSQL Database', description: 'MongoDB, Redis, DynamoDB, etc.' },
|
|
68
|
-
{ value: 'none', name: 'No Database', description: 'No persistent data storage needed' }
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
export async function initCommand(options: InitOptions) {
|
|
72
|
-
showBanner();
|
|
73
|
-
showInstructions();
|
|
74
|
-
|
|
75
|
-
// First-run initialization
|
|
76
|
-
await ensureDataInitialized();
|
|
77
|
-
|
|
78
|
-
// Check for guideline updates (non-blocking)
|
|
79
|
-
checkForUpdatesInBackground();
|
|
80
|
-
|
|
81
|
-
const generator = await ConfigGenerator.create();
|
|
82
|
-
const projectPath = process.cwd();
|
|
83
|
-
const wizard = new WizardStateManager();
|
|
84
|
-
|
|
85
|
-
const spinner = ora('Detecting project...').start();
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
// Detect project
|
|
89
|
-
const detected = await generator.detectProject(projectPath);
|
|
90
|
-
spinner.succeed('Project detected');
|
|
91
|
-
|
|
92
|
-
wizard.updateState({
|
|
93
|
-
detectedLanguage: detected.language !== 'unknown' ? detected.language : undefined,
|
|
94
|
-
detectedProjectName: detected.name,
|
|
95
|
-
hasExistingConfig: detected.hasExistingConfig
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// Show detection results in box
|
|
99
|
-
console.log('\n' + createSummaryBox('š Project Detection', [
|
|
100
|
-
{ label: 'Name', value: detected.name },
|
|
101
|
-
{ label: 'Language', value: detected.language !== 'unknown' ? detected.language : 'Not detected' }
|
|
102
|
-
]));
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// Check for existing config
|
|
107
|
-
if (detected.hasExistingConfig && !options.force) {
|
|
108
|
-
console.log(chalk.yellow('\nā ļø Existing AI config detected'));
|
|
109
|
-
|
|
110
|
-
const action = await select({
|
|
111
|
-
message: 'How would you like to proceed?',
|
|
112
|
-
choices: [
|
|
113
|
-
{ value: 'overwrite', name: 'Overwrite existing config', description: 'Keep other AI configs, replace matching ones' },
|
|
114
|
-
{ value: 'clear', name: 'Clear all configs first', description: 'Remove all AI configs, then generate new' },
|
|
115
|
-
{ value: 'cancel', name: 'Cancel', description: 'Exit without making changes' }
|
|
116
|
-
]
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
if (action === 'cancel') {
|
|
120
|
-
console.log(chalk.gray('\nCancelled.'));
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (action === 'clear') {
|
|
125
|
-
// Import and run clear command logic
|
|
126
|
-
const { clearCommand } = await import('./clear.js');
|
|
127
|
-
await clearCommand({ force: true });
|
|
128
|
-
console.log(''); // Add spacing
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Wizard loop with back navigation
|
|
133
|
-
while (!wizard.isComplete()) {
|
|
134
|
-
const state = wizard.getState();
|
|
135
|
-
|
|
136
|
-
switch (state.currentStep) {
|
|
137
|
-
case 'language':
|
|
138
|
-
await handleLanguageStep(wizard, detected.language);
|
|
139
|
-
break;
|
|
140
|
-
|
|
141
|
-
case 'projectType':
|
|
142
|
-
if (await handleProjectTypeStep(wizard) === BACK_VALUE) {
|
|
143
|
-
wizard.goBack();
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
break;
|
|
147
|
-
|
|
148
|
-
case 'assistant':
|
|
149
|
-
if (await handleAssistantStep(wizard, options) === BACK_VALUE) {
|
|
150
|
-
wizard.goBack();
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
break;
|
|
154
|
-
|
|
155
|
-
case 'setupType':
|
|
156
|
-
if (await handleSetupTypeStep(wizard) === BACK_VALUE) {
|
|
157
|
-
wizard.goBack();
|
|
158
|
-
continue;
|
|
159
|
-
}
|
|
160
|
-
break;
|
|
161
|
-
|
|
162
|
-
case 'architecture':
|
|
163
|
-
if (await handleArchitectureStep(wizard, options) === BACK_VALUE) {
|
|
164
|
-
wizard.goBack();
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
break;
|
|
168
|
-
|
|
169
|
-
case 'datasource':
|
|
170
|
-
if (await handleDatasourceStep(wizard) === BACK_VALUE) {
|
|
171
|
-
wizard.goBack();
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
break;
|
|
175
|
-
|
|
176
|
-
case 'level':
|
|
177
|
-
if (await handleLevelStep(wizard, options) === BACK_VALUE) {
|
|
178
|
-
wizard.goBack();
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
break;
|
|
182
|
-
|
|
183
|
-
case 'guidelines':
|
|
184
|
-
if (state.setupType === 'custom') {
|
|
185
|
-
if (await handleGuidelinesStep(wizard) === BACK_VALUE) {
|
|
186
|
-
wizard.goBack();
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
} else {
|
|
190
|
-
wizard.goToNextStep();
|
|
191
|
-
}
|
|
192
|
-
break;
|
|
193
|
-
|
|
194
|
-
case 'summary': {
|
|
195
|
-
const shouldGenerate = await handleSummaryStep(wizard);
|
|
196
|
-
if (shouldGenerate === BACK_VALUE) {
|
|
197
|
-
wizard.goBack();
|
|
198
|
-
continue;
|
|
199
|
-
} else if (!shouldGenerate) {
|
|
200
|
-
console.log(chalk.gray('\nCancelled.'));
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (state.currentStep !== 'summary') {
|
|
208
|
-
wizard.goToNextStep();
|
|
209
|
-
} else {
|
|
210
|
-
break;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Generate configuration
|
|
215
|
-
const state = wizard.getState();
|
|
216
|
-
const selection: ProfileSelection = {
|
|
217
|
-
assistant: state.assistant!,
|
|
218
|
-
language: state.language!,
|
|
219
|
-
level: state.level!,
|
|
220
|
-
architecture: state.architecture!,
|
|
221
|
-
projectType: state.projectType!,
|
|
222
|
-
projectName: detected.name,
|
|
223
|
-
datasource: state.datasource!
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
spinner.start('Generating configuration...');
|
|
227
|
-
|
|
228
|
-
const result = await generator.generate({
|
|
229
|
-
projectPath,
|
|
230
|
-
selection,
|
|
231
|
-
customGuidelineIds: state.selectedGuidelineIds,
|
|
232
|
-
dryRun: options.dryRun
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
if (!result.success) {
|
|
236
|
-
spinner.fail('Generation failed');
|
|
237
|
-
console.error(chalk.red('\nā Errors:'));
|
|
238
|
-
result.errors.forEach(err => console.error(chalk.red(` - ${err}`)));
|
|
239
|
-
process.exit(1);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
spinner.succeed(options.dryRun ? 'Dry run complete' : 'Configuration generated');
|
|
243
|
-
|
|
244
|
-
// Show results
|
|
245
|
-
if (options.dryRun) {
|
|
246
|
-
console.log(chalk.yellow('\nš Files that would be generated:'));
|
|
247
|
-
} else {
|
|
248
|
-
console.log(chalk.green('\nā
Generated files:'));
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
result.filesGenerated.forEach(file => {
|
|
252
|
-
const relativePath = file.replace(projectPath, '').replace(/^[/\\]/, '');
|
|
253
|
-
console.log(chalk.gray(` ${relativePath}`));
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
if (!options.dryRun) {
|
|
257
|
-
console.log(chalk.cyan('\nš Next steps:'));
|
|
258
|
-
printNextSteps(state.assistant!);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
} catch (error) {
|
|
262
|
-
spinner.fail('Error');
|
|
263
|
-
console.error(chalk.red(`\nā ${(error as Error).message}`));
|
|
264
|
-
process.exit(1);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
async function handleLanguageStep(wizard: WizardStateManager, detectedLanguage?: Language): Promise<void> {
|
|
269
|
-
let language: Language;
|
|
270
|
-
|
|
271
|
-
if (wizard.getState().language) return;
|
|
272
|
-
|
|
273
|
-
if (detectedLanguage && detectedLanguage !== 'unknown') {
|
|
274
|
-
const useDetected = await confirm({
|
|
275
|
-
message: `Use detected language: ${chalk.cyan(detectedLanguage)}?`,
|
|
276
|
-
default: true
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
if (useDetected) {
|
|
280
|
-
language = detectedLanguage;
|
|
281
|
-
} else {
|
|
282
|
-
language = await select({
|
|
283
|
-
message: 'Select language:',
|
|
284
|
-
choices: LANGUAGES.map(l => ({ value: l.value, name: l.name }))
|
|
285
|
-
}) as Language;
|
|
286
|
-
}
|
|
287
|
-
} else {
|
|
288
|
-
language = await select({
|
|
289
|
-
message: 'Select language:',
|
|
290
|
-
choices: LANGUAGES.map(l => ({ value: l.value, name: l.name }))
|
|
291
|
-
}) as Language;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
wizard.updateState({ language });
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
async function handleProjectTypeStep(wizard: WizardStateManager): Promise<string> {
|
|
298
|
-
const state = wizard.getState();
|
|
299
|
-
if (state.projectType) return state.projectType;
|
|
300
|
-
|
|
301
|
-
const choices = addBackOption(
|
|
302
|
-
PROJECT_TYPES.map(pt => ({
|
|
303
|
-
value: pt.value,
|
|
304
|
-
name: pt.name,
|
|
305
|
-
description: pt.description
|
|
306
|
-
})),
|
|
307
|
-
wizard.canGoBack()
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
const projectType = await select({
|
|
311
|
-
message: 'What type of project is this?',
|
|
312
|
-
choices
|
|
313
|
-
}) as ProjectType | typeof BACK_VALUE;
|
|
314
|
-
|
|
315
|
-
if (projectType !== BACK_VALUE) {
|
|
316
|
-
wizard.updateState({ projectType: projectType as ProjectType });
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
return projectType;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
async function handleAssistantStep(wizard: WizardStateManager, options: InitOptions): Promise<string> {
|
|
323
|
-
const state = wizard.getState();
|
|
324
|
-
if (state.assistant) return state.assistant;
|
|
325
|
-
|
|
326
|
-
if (options.assistant) {
|
|
327
|
-
wizard.updateState({ assistant: options.assistant as AIAssistant });
|
|
328
|
-
return options.assistant;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
const choices = addBackOption(
|
|
332
|
-
ASSISTANTS.map(a => ({
|
|
333
|
-
value: a.value,
|
|
334
|
-
name: a.name,
|
|
335
|
-
description: a.description
|
|
336
|
-
})),
|
|
337
|
-
wizard.canGoBack()
|
|
338
|
-
);
|
|
339
|
-
|
|
340
|
-
const assistant = await select({
|
|
341
|
-
message: 'Which AI assistant?',
|
|
342
|
-
choices
|
|
343
|
-
}) as AIAssistant | typeof BACK_VALUE;
|
|
344
|
-
|
|
345
|
-
if (assistant !== BACK_VALUE) {
|
|
346
|
-
wizard.updateState({ assistant: assistant as AIAssistant });
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return assistant;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
async function handleSetupTypeStep(wizard: WizardStateManager): Promise<string> {
|
|
353
|
-
const choices = addBackOption(
|
|
354
|
-
[
|
|
355
|
-
{ value: 'quick', name: 'Quick Setup', description: 'Recommended settings for common use cases' },
|
|
356
|
-
{ value: 'custom', name: 'Custom', description: 'Select individual guidelines' }
|
|
357
|
-
],
|
|
358
|
-
wizard.canGoBack()
|
|
359
|
-
);
|
|
360
|
-
|
|
361
|
-
const setupType = await select({
|
|
362
|
-
message: 'Setup type?',
|
|
363
|
-
choices
|
|
364
|
-
}) as 'quick' | 'custom' | typeof BACK_VALUE;
|
|
365
|
-
|
|
366
|
-
if (setupType !== BACK_VALUE) {
|
|
367
|
-
wizard.updateState({ setupType: setupType as 'quick' | 'custom' });
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
return setupType;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
async function handleArchitectureStep(wizard: WizardStateManager, options: InitOptions): Promise<string> {
|
|
374
|
-
const state = wizard.getState();
|
|
375
|
-
if (state.architecture) return state.architecture;
|
|
376
|
-
|
|
377
|
-
if (options.architecture) {
|
|
378
|
-
wizard.updateState({ architecture: options.architecture as ArchitectureType });
|
|
379
|
-
return options.architecture;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
const choices = addBackOption(
|
|
383
|
-
ARCHITECTURES.map(a => ({
|
|
384
|
-
value: a.value,
|
|
385
|
-
name: a.name,
|
|
386
|
-
description: a.description
|
|
387
|
-
})),
|
|
388
|
-
wizard.canGoBack()
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
const architecture = await select({
|
|
392
|
-
message: 'Architecture pattern?',
|
|
393
|
-
choices,
|
|
394
|
-
default: 'modular-monolith'
|
|
395
|
-
}) as ArchitectureType | typeof BACK_VALUE;
|
|
396
|
-
|
|
397
|
-
if (architecture !== BACK_VALUE) {
|
|
398
|
-
wizard.updateState({ architecture: architecture as ArchitectureType });
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
return architecture;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
async function handleDatasourceStep(wizard: WizardStateManager): Promise<string> {
|
|
405
|
-
const state = wizard.getState();
|
|
406
|
-
if (state.datasource) return state.datasource;
|
|
407
|
-
|
|
408
|
-
const choices = addBackOption(
|
|
409
|
-
DATASOURCES.map(d => ({
|
|
410
|
-
value: d.value,
|
|
411
|
-
name: d.name,
|
|
412
|
-
description: d.description
|
|
413
|
-
})),
|
|
414
|
-
wizard.canGoBack()
|
|
415
|
-
);
|
|
416
|
-
|
|
417
|
-
const datasource = await select({
|
|
418
|
-
message: 'Data storage?',
|
|
419
|
-
choices,
|
|
420
|
-
default: 'sql'
|
|
421
|
-
}) as DatasourceType | typeof BACK_VALUE;
|
|
422
|
-
|
|
423
|
-
if (datasource !== BACK_VALUE) {
|
|
424
|
-
wizard.updateState({ datasource: datasource as DatasourceType });
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
return datasource;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
async function handleLevelStep(wizard: WizardStateManager, options: InitOptions): Promise<string> {
|
|
431
|
-
const state = wizard.getState();
|
|
432
|
-
|
|
433
|
-
if (options.level) {
|
|
434
|
-
wizard.updateState({ level: options.level as InstructionLevel });
|
|
435
|
-
return options.level;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
const levelsWithMetrics = await getLevelsWithMetrics(
|
|
439
|
-
state.language!,
|
|
440
|
-
state.architecture!,
|
|
441
|
-
state.datasource
|
|
442
|
-
);
|
|
443
|
-
|
|
444
|
-
const choices = addBackOption(
|
|
445
|
-
levelsWithMetrics.map(l => ({
|
|
446
|
-
value: l.value,
|
|
447
|
-
name: l.name,
|
|
448
|
-
description: l.description
|
|
449
|
-
})),
|
|
450
|
-
wizard.canGoBack()
|
|
451
|
-
);
|
|
452
|
-
|
|
453
|
-
const level = await select({
|
|
454
|
-
message: 'Instruction detail level?',
|
|
455
|
-
choices,
|
|
456
|
-
default: 'standard'
|
|
457
|
-
}) as InstructionLevel | typeof BACK_VALUE;
|
|
458
|
-
|
|
459
|
-
if (level !== BACK_VALUE) {
|
|
460
|
-
wizard.updateState({ level: level as InstructionLevel });
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
return level;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
async function handleGuidelinesStep(wizard: WizardStateManager): Promise<string> {
|
|
467
|
-
const state = wizard.getState();
|
|
468
|
-
|
|
469
|
-
const selectedIds = await selectGuidelines(
|
|
470
|
-
state.language!,
|
|
471
|
-
state.level!,
|
|
472
|
-
state.architecture!,
|
|
473
|
-
wizard.canGoBack(),
|
|
474
|
-
state.datasource
|
|
475
|
-
);
|
|
476
|
-
|
|
477
|
-
if (selectedIds === BACK_VALUE) {
|
|
478
|
-
return BACK_VALUE;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
wizard.updateState({ selectedGuidelineIds: selectedIds as string[] });
|
|
482
|
-
return 'OK';
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
async function handleSummaryStep(wizard: WizardStateManager): Promise<boolean | string> {
|
|
486
|
-
const state = wizard.getState();
|
|
487
|
-
const loader = await GuidelineLoader.create();
|
|
488
|
-
|
|
489
|
-
const guidelineIds = state.selectedGuidelineIds || loader.getGuidelinesForProfile(
|
|
490
|
-
state.language!,
|
|
491
|
-
state.level!,
|
|
492
|
-
state.architecture!,
|
|
493
|
-
state.datasource
|
|
494
|
-
);
|
|
495
|
-
|
|
496
|
-
const metrics = loader.getMetrics(guidelineIds);
|
|
497
|
-
|
|
498
|
-
console.log('\n' + createSummaryBox('š Configuration Summary', [
|
|
499
|
-
{ label: 'Assistant', value: state.assistant! },
|
|
500
|
-
{ label: 'Language', value: state.language! },
|
|
501
|
-
{ label: 'Project Type', value: state.projectType! },
|
|
502
|
-
{ label: 'Architecture', value: state.architecture! },
|
|
503
|
-
{ label: 'Data Storage', value: state.datasource! },
|
|
504
|
-
{ label: 'Level', value: state.level! },
|
|
505
|
-
{ label: 'Setup Type', value: state.setupType || 'standard' }
|
|
506
|
-
]));
|
|
507
|
-
|
|
508
|
-
console.log('\n' + createMetricsBox([
|
|
509
|
-
{ label: 'guidelines', value: metrics.guidelineCount },
|
|
510
|
-
{ label: 'hooks', value: metrics.hooksCount },
|
|
511
|
-
{ label: 'sub-agents', value: metrics.subAgentsCount },
|
|
512
|
-
{ label: 'estimated size', value: metrics.estimatedSize }
|
|
513
|
-
]));
|
|
514
|
-
|
|
515
|
-
// Show selected guidelines if in custom mode
|
|
516
|
-
if (state.setupType === 'custom' && state.selectedGuidelineIds && state.selectedGuidelineIds.length > 0) {
|
|
517
|
-
console.log(chalk.cyan('\nš Selected Guidelines:'));
|
|
518
|
-
const guidelineNames = state.selectedGuidelineIds.map(id => {
|
|
519
|
-
const mapping = loader.getMapping(id);
|
|
520
|
-
return mapping ? ` ⢠${mapping.category || 'General'}: ${id}` : ` ⢠${id}`;
|
|
521
|
-
});
|
|
522
|
-
console.log(guidelineNames.slice(0, 10).join('\n'));
|
|
523
|
-
if (guidelineNames.length > 10) {
|
|
524
|
-
console.log(chalk.gray(` ... and ${guidelineNames.length - 10} more`));
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
console.log('');
|
|
529
|
-
|
|
530
|
-
const shouldGenerate = await select({
|
|
531
|
-
message: 'Proceed with generation?',
|
|
532
|
-
choices: [
|
|
533
|
-
{ value: 'yes', name: 'Yes, generate configuration', description: 'Create config files' },
|
|
534
|
-
...(wizard.canGoBack() ? [{ value: BACK_VALUE, name: 'ā Back', description: 'Modify settings' }] : []),
|
|
535
|
-
{ value: 'no', name: 'Cancel', description: 'Exit without generating' }
|
|
536
|
-
]
|
|
537
|
-
});
|
|
538
|
-
|
|
539
|
-
if (shouldGenerate === 'yes') {
|
|
540
|
-
return true;
|
|
541
|
-
} else if (shouldGenerate === BACK_VALUE) {
|
|
542
|
-
return BACK_VALUE;
|
|
543
|
-
} else {
|
|
544
|
-
return false;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
async function getLevelsWithMetrics(language: Language, architecture: ArchitectureType, datasource?: DatasourceType): Promise<{ value: InstructionLevel; name: string; description: string }[]> {
|
|
549
|
-
const loader = await GuidelineLoader.create();
|
|
550
|
-
const levels: InstructionLevel[] = ['basic', 'standard', 'expert', 'full'];
|
|
551
|
-
|
|
552
|
-
return levels.map(level => {
|
|
553
|
-
const guidelineIds = loader.getGuidelinesForProfile(language, level, architecture, datasource);
|
|
554
|
-
const metrics = loader.getMetrics(guidelineIds);
|
|
555
|
-
|
|
556
|
-
const descriptions: Record<InstructionLevel, string> = {
|
|
557
|
-
basic: 'Essential guidelines for quick projects',
|
|
558
|
-
standard: 'Production-ready practices',
|
|
559
|
-
expert: 'Advanced patterns for scaling',
|
|
560
|
-
full: 'Everything - all guidelines'
|
|
561
|
-
};
|
|
562
|
-
|
|
563
|
-
return {
|
|
564
|
-
value: level,
|
|
565
|
-
name: `${level.charAt(0).toUpperCase() + level.slice(1)}`,
|
|
566
|
-
description: `${descriptions[level]} (${metrics.guidelineCount} guidelines, ${metrics.hooksCount} hooks, ${metrics.subAgentsCount} agents, ${metrics.estimatedSize})`
|
|
567
|
-
};
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
function printNextSteps(assistant: AIAssistant) {
|
|
572
|
-
switch (assistant) {
|
|
573
|
-
case 'claude-code':
|
|
574
|
-
console.log(chalk.gray(' 1. Review .claude/CLAUDE.md'));
|
|
575
|
-
console.log(chalk.gray(' 2. Check .claude/settings.json for hooks'));
|
|
576
|
-
console.log(chalk.gray(' 3. Review sub-agents in .claude/agents/'));
|
|
577
|
-
console.log(chalk.gray(' 4. Open project in Claude Code'));
|
|
578
|
-
break;
|
|
579
|
-
case 'copilot':
|
|
580
|
-
console.log(chalk.gray(' 1. Review .github/copilot-instructions.md'));
|
|
581
|
-
console.log(chalk.gray(' 2. Check .github/instructions/ for details'));
|
|
582
|
-
console.log(chalk.gray(' 3. Open project in VS Code'));
|
|
583
|
-
break;
|
|
584
|
-
case 'gemini':
|
|
585
|
-
console.log(chalk.gray(' 1. Review .gemini/instructions.md'));
|
|
586
|
-
console.log(chalk.gray(' 2. Configure Gemini integration'));
|
|
587
|
-
break;
|
|
588
|
-
case 'antigravity':
|
|
589
|
-
console.log(chalk.gray(' 1. Review .agent/rules/instructions.md'));
|
|
590
|
-
console.log(chalk.gray(' 2. Open project in Antigravity'));
|
|
591
|
-
break;
|
|
592
|
-
case 'codex':
|
|
593
|
-
console.log(chalk.gray(' 1. Review .codex/instructions.md'));
|
|
594
|
-
console.log(chalk.gray(' 2. Configure Codex integration'));
|
|
595
|
-
break;
|
|
596
|
-
}
|
|
597
|
-
console.log(chalk.gray(' \n Also check AGENTS.md for universal instructions'));
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
async function checkForUpdatesInBackground() {
|
|
601
|
-
try {
|
|
602
|
-
const loader = await GuidelineLoader.create();
|
|
603
|
-
const currentVersion = loader.getVersion();
|
|
604
|
-
|
|
605
|
-
if (currentVersion === 'embedded' || currentVersion === 'unknown') {
|
|
606
|
-
return;
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
const response = await fetch(GITHUB_RELEASES_URL, {
|
|
610
|
-
headers: {
|
|
611
|
-
'Accept': 'application/vnd.github+json',
|
|
612
|
-
'User-Agent': CONFIG.USER_AGENT
|
|
613
|
-
}
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
if (!response.ok) return;
|
|
617
|
-
|
|
618
|
-
const data = await response.json() as { tag_name: string };
|
|
619
|
-
const latestVersion = data.tag_name.replace(/^v/, '');
|
|
620
|
-
|
|
621
|
-
const currentParts = currentVersion.split('.').map(Number);
|
|
622
|
-
const latestParts = latestVersion.split('.').map(Number);
|
|
623
|
-
|
|
624
|
-
let needsUpdate = false;
|
|
625
|
-
for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
|
|
626
|
-
const curr = currentParts[i] || 0;
|
|
627
|
-
const lat = latestParts[i] || 0;
|
|
628
|
-
|
|
629
|
-
if (lat > curr) {
|
|
630
|
-
needsUpdate = true;
|
|
631
|
-
break;
|
|
632
|
-
}
|
|
633
|
-
if (lat < curr) break;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
if (needsUpdate) {
|
|
637
|
-
console.log(chalk.yellow(`\n š¦ New guidelines available: v${latestVersion}`));
|
|
638
|
-
console.log(chalk.gray(` Run ${chalk.white('aicgen update')} to download\n`));
|
|
639
|
-
}
|
|
640
|
-
} catch {
|
|
641
|
-
// Silently fail if can't check for updates
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
|