lynxprompt 0.3.1 → 0.4.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/dist/index.js +1038 -125
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -200,12 +200,7 @@ async function loginCommand() {
|
|
|
200
200
|
pollSpinner.succeed("Authentication successful!");
|
|
201
201
|
setToken(result.token);
|
|
202
202
|
setUser(result.user);
|
|
203
|
-
|
|
204
|
-
console.log(chalk.green(`\u2705 Logged in as ${chalk.bold(result.user.email)}`));
|
|
205
|
-
console.log(chalk.gray(` Plan: ${result.user.plan}`));
|
|
206
|
-
console.log(chalk.gray(` Token stored securely in config`));
|
|
207
|
-
console.log();
|
|
208
|
-
console.log(chalk.cyan("You're ready to use LynxPrompt CLI!"));
|
|
203
|
+
displayWelcome(result.user);
|
|
209
204
|
return;
|
|
210
205
|
}
|
|
211
206
|
if (result.status === "expired") {
|
|
@@ -259,6 +254,53 @@ async function tryOpenBrowser(url) {
|
|
|
259
254
|
function sleep(ms) {
|
|
260
255
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
261
256
|
}
|
|
257
|
+
function displayWelcome(user) {
|
|
258
|
+
const plan = user.plan?.toUpperCase() || "FREE";
|
|
259
|
+
const name = user.name || user.email.split("@")[0];
|
|
260
|
+
const planConfig = {
|
|
261
|
+
FREE: { color: chalk.gray, emoji: "\u{1F193}", badge: "Free" },
|
|
262
|
+
PRO: { color: chalk.cyan, emoji: "\u26A1", badge: "Pro" },
|
|
263
|
+
MAX: { color: chalk.magenta, emoji: "\u{1F680}", badge: "Max" },
|
|
264
|
+
TEAMS: { color: chalk.yellow, emoji: "\u{1F465}", badge: "Teams" }
|
|
265
|
+
};
|
|
266
|
+
const config2 = planConfig[plan] || planConfig.FREE;
|
|
267
|
+
console.log();
|
|
268
|
+
console.log(chalk.bold("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
269
|
+
console.log(chalk.bold("\u2502") + " " + chalk.bold("\u2502"));
|
|
270
|
+
console.log(chalk.bold("\u2502") + chalk.green.bold(` ${config2.emoji} Welcome to LynxPrompt CLI!`) + " " + chalk.bold("\u2502"));
|
|
271
|
+
console.log(chalk.bold("\u2502") + " " + chalk.bold("\u2502"));
|
|
272
|
+
console.log(chalk.bold("\u2502") + ` ${chalk.white("User:")} ${chalk.bold(name.padEnd(38))}` + chalk.bold("\u2502"));
|
|
273
|
+
console.log(chalk.bold("\u2502") + ` ${chalk.white("Plan:")} ${config2.color(config2.badge.padEnd(38))}` + chalk.bold("\u2502"));
|
|
274
|
+
console.log(chalk.bold("\u2502") + " " + chalk.bold("\u2502"));
|
|
275
|
+
console.log(chalk.bold("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
276
|
+
console.log();
|
|
277
|
+
console.log(chalk.bold("\u{1F4CB} Your CLI Capabilities:"));
|
|
278
|
+
console.log();
|
|
279
|
+
console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt init") + chalk.gray(" - Generate config files"));
|
|
280
|
+
console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt wizard") + chalk.gray(" - Interactive wizard"));
|
|
281
|
+
console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt list") + chalk.gray(" - List your blueprints"));
|
|
282
|
+
console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt pull <id>") + chalk.gray(" - Download blueprints"));
|
|
283
|
+
console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt push") + chalk.gray(" - Upload blueprints to marketplace"));
|
|
284
|
+
console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt link") + chalk.gray(" - Link project to blueprint"));
|
|
285
|
+
console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt sync") + chalk.gray(" - Sync linked blueprints"));
|
|
286
|
+
console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt diff") + chalk.gray(" - Compare local vs remote"));
|
|
287
|
+
if (plan === "PRO" || plan === "MAX" || plan === "TEAMS") {
|
|
288
|
+
console.log();
|
|
289
|
+
console.log(chalk.cyan(" \u26A1") + " " + chalk.white("Advanced wizards") + chalk.gray(" - More customization options"));
|
|
290
|
+
console.log(chalk.cyan(" \u26A1") + " " + chalk.white("Sell blueprints") + chalk.gray(" - Monetize your configurations"));
|
|
291
|
+
}
|
|
292
|
+
if (plan === "MAX" || plan === "TEAMS") {
|
|
293
|
+
console.log(chalk.magenta(" \u{1F680}") + " " + chalk.white("All paid blueprints") + chalk.gray(" - Access premium content"));
|
|
294
|
+
console.log(chalk.magenta(" \u{1F680}") + " " + chalk.white("Priority support") + chalk.gray(" - Get help faster"));
|
|
295
|
+
}
|
|
296
|
+
if (plan === "TEAMS") {
|
|
297
|
+
console.log(chalk.yellow(" \u{1F465}") + " " + chalk.white("Team blueprints") + chalk.gray(" - Share with your team"));
|
|
298
|
+
console.log(chalk.yellow(" \u{1F465}") + " " + chalk.white("SSO integration") + chalk.gray(" - Enterprise authentication"));
|
|
299
|
+
}
|
|
300
|
+
console.log();
|
|
301
|
+
console.log(chalk.gray("Token stored securely. Run ") + chalk.cyan("lynxprompt --help") + chalk.gray(" to see all commands."));
|
|
302
|
+
console.log();
|
|
303
|
+
}
|
|
262
304
|
|
|
263
305
|
// src/commands/logout.ts
|
|
264
306
|
import chalk2 from "chalk";
|
|
@@ -1974,7 +2016,17 @@ var PLATFORM_FILES = {
|
|
|
1974
2016
|
claude: "CLAUDE.md",
|
|
1975
2017
|
copilot: ".github/copilot-instructions.md",
|
|
1976
2018
|
windsurf: ".windsurfrules",
|
|
1977
|
-
zed: ".zed/instructions.md"
|
|
2019
|
+
zed: ".zed/instructions.md",
|
|
2020
|
+
aider: ".aider.conf.yml",
|
|
2021
|
+
cline: ".clinerules",
|
|
2022
|
+
continue: ".continue/rules.md",
|
|
2023
|
+
cody: ".cody/rules.md",
|
|
2024
|
+
amazonq: ".amazonq/rules/project.md",
|
|
2025
|
+
tabnine: ".tabnine.yaml",
|
|
2026
|
+
supermaven: ".supermaven/rules.md",
|
|
2027
|
+
codegpt: ".codegpt/rules.md",
|
|
2028
|
+
void: ".void/rules.md",
|
|
2029
|
+
goose: ".goosehints"
|
|
1978
2030
|
};
|
|
1979
2031
|
var PERSONA_DESCRIPTIONS = {
|
|
1980
2032
|
backend: "a senior backend developer specializing in APIs, databases, and microservices architecture",
|
|
@@ -1995,6 +2047,8 @@ var STACK_NAMES = {
|
|
|
1995
2047
|
ruby: "Ruby",
|
|
1996
2048
|
php: "PHP",
|
|
1997
2049
|
swift: "Swift",
|
|
2050
|
+
kotlin: "Kotlin",
|
|
2051
|
+
cpp: "C/C++",
|
|
1998
2052
|
react: "React",
|
|
1999
2053
|
nextjs: "Next.js",
|
|
2000
2054
|
vue: "Vue.js",
|
|
@@ -2007,10 +2061,44 @@ var STACK_NAMES = {
|
|
|
2007
2061
|
spring: "Spring Boot",
|
|
2008
2062
|
rails: "Ruby on Rails",
|
|
2009
2063
|
laravel: "Laravel",
|
|
2064
|
+
nestjs: "NestJS",
|
|
2065
|
+
vite: "Vite",
|
|
2066
|
+
"react-native": "React Native",
|
|
2067
|
+
postgresql: "PostgreSQL",
|
|
2068
|
+
mysql: "MySQL",
|
|
2069
|
+
mongodb: "MongoDB",
|
|
2070
|
+
redis: "Redis",
|
|
2071
|
+
sqlite: "SQLite",
|
|
2072
|
+
supabase: "Supabase",
|
|
2073
|
+
firebase: "Firebase",
|
|
2010
2074
|
prisma: "Prisma",
|
|
2011
2075
|
tailwind: "Tailwind CSS",
|
|
2012
2076
|
fastify: "Fastify"
|
|
2013
2077
|
};
|
|
2078
|
+
var NAMING_DESCRIPTIONS = {
|
|
2079
|
+
language_default: "follow idiomatic conventions for the primary language",
|
|
2080
|
+
camelCase: "use camelCase for variables and functions",
|
|
2081
|
+
snake_case: "use snake_case for variables and functions",
|
|
2082
|
+
PascalCase: "use PascalCase for classes and types",
|
|
2083
|
+
"kebab-case": "use kebab-case for file names and CSS classes"
|
|
2084
|
+
};
|
|
2085
|
+
var AI_BEHAVIOR_DESCRIPTIONS = {
|
|
2086
|
+
explain_changes: "Always explain what changes you're making and why before implementing them",
|
|
2087
|
+
preserve_style: "Preserve and follow the existing code style in the project",
|
|
2088
|
+
minimal_changes: "Make minimal, focused changes - avoid unnecessary refactoring",
|
|
2089
|
+
no_comments: "Avoid adding unnecessary comments; code should be self-documenting",
|
|
2090
|
+
prefer_simple: "Prefer simpler solutions over clever ones",
|
|
2091
|
+
test_first: "Write tests before implementing new functionality (TDD)",
|
|
2092
|
+
no_console: "Remove console.log/print statements before committing",
|
|
2093
|
+
type_strict: "Be strict with types - avoid any/Any/Object types"
|
|
2094
|
+
};
|
|
2095
|
+
var IMPORTANT_FILES_PATHS = {
|
|
2096
|
+
readme: "README.md",
|
|
2097
|
+
package: "package.json or pyproject.toml",
|
|
2098
|
+
tsconfig: "tsconfig.json or similar config",
|
|
2099
|
+
architecture: "ARCHITECTURE.md",
|
|
2100
|
+
contributing: "CONTRIBUTING.md"
|
|
2101
|
+
};
|
|
2014
2102
|
var BOUNDARIES = {
|
|
2015
2103
|
conservative: {
|
|
2016
2104
|
always: ["Read any file in the project", "Run lint and format commands"],
|
|
@@ -2069,6 +2157,12 @@ var BOUNDARIES = {
|
|
|
2069
2157
|
]
|
|
2070
2158
|
}
|
|
2071
2159
|
};
|
|
2160
|
+
var TEST_LEVEL_DESCRIPTIONS = {
|
|
2161
|
+
smoke: "Quick sanity checks for critical paths",
|
|
2162
|
+
unit: "Unit tests for individual functions and components",
|
|
2163
|
+
integration: "Integration tests for component interactions",
|
|
2164
|
+
e2e: "End-to-end tests for full user flows"
|
|
2165
|
+
};
|
|
2072
2166
|
function generateConfig(options) {
|
|
2073
2167
|
const files = {};
|
|
2074
2168
|
for (const platform of options.platforms) {
|
|
@@ -2082,8 +2176,12 @@ function generateConfig(options) {
|
|
|
2082
2176
|
function generateFileContent(options, platform) {
|
|
2083
2177
|
const sections = [];
|
|
2084
2178
|
const isMdc = platform === "cursor";
|
|
2085
|
-
const
|
|
2086
|
-
const
|
|
2179
|
+
const isYaml = platform === "aider" || platform === "tabnine";
|
|
2180
|
+
const isPlainText = platform === "windsurf" || platform === "cline" || platform === "goose";
|
|
2181
|
+
const isMarkdown = !isMdc && !isYaml && !isPlainText;
|
|
2182
|
+
if (isYaml) {
|
|
2183
|
+
return generateYamlConfig(options, platform);
|
|
2184
|
+
}
|
|
2087
2185
|
if (isMdc) {
|
|
2088
2186
|
sections.push("---");
|
|
2089
2187
|
sections.push(`description: "${options.name} - AI coding rules"`);
|
|
@@ -2098,6 +2196,23 @@ function generateFileContent(options, platform) {
|
|
|
2098
2196
|
sections.push(`# ${options.name} - AI Assistant Configuration`);
|
|
2099
2197
|
sections.push("");
|
|
2100
2198
|
}
|
|
2199
|
+
if (options.projectType) {
|
|
2200
|
+
const typeContexts = {
|
|
2201
|
+
work: "This is a professional/enterprise project. Follow strict procedures and maintain high code quality.",
|
|
2202
|
+
leisure: "This is a personal/hobby project. Feel free to be more experimental and creative.",
|
|
2203
|
+
opensource: "This is an open-source project. Consider community guidelines and contribution standards.",
|
|
2204
|
+
learning: "This is an educational project. Explain concepts and be patient with learning-focused approaches."
|
|
2205
|
+
};
|
|
2206
|
+
if (typeContexts[options.projectType]) {
|
|
2207
|
+
if (isMarkdown || isMdc) {
|
|
2208
|
+
sections.push(`> **Project Context:** ${typeContexts[options.projectType]}`);
|
|
2209
|
+
sections.push("");
|
|
2210
|
+
} else {
|
|
2211
|
+
sections.push(`Project Context: ${typeContexts[options.projectType]}`);
|
|
2212
|
+
sections.push("");
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2101
2216
|
const personaDesc = PERSONA_DESCRIPTIONS[options.persona] || options.persona;
|
|
2102
2217
|
if (isMarkdown || isMdc) {
|
|
2103
2218
|
sections.push("## Persona");
|
|
@@ -2128,7 +2243,25 @@ function generateFileContent(options, platform) {
|
|
|
2128
2243
|
}
|
|
2129
2244
|
sections.push("");
|
|
2130
2245
|
}
|
|
2131
|
-
|
|
2246
|
+
if (options.repoHost || options.license || options.conventionalCommits) {
|
|
2247
|
+
if (isMarkdown || isMdc) {
|
|
2248
|
+
sections.push("## Repository");
|
|
2249
|
+
sections.push("");
|
|
2250
|
+
if (options.repoHost) {
|
|
2251
|
+
sections.push(`- **Host:** ${options.repoHost.charAt(0).toUpperCase() + options.repoHost.slice(1)}`);
|
|
2252
|
+
}
|
|
2253
|
+
if (options.license && options.license !== "none") {
|
|
2254
|
+
sections.push(`- **License:** ${options.license.toUpperCase()}`);
|
|
2255
|
+
}
|
|
2256
|
+
if (options.conventionalCommits) {
|
|
2257
|
+
sections.push("- **Commits:** Follow [Conventional Commits](https://conventionalcommits.org) format");
|
|
2258
|
+
}
|
|
2259
|
+
sections.push("");
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
const hasCommands = options.commands && Object.values(options.commands).some(
|
|
2263
|
+
(v) => Array.isArray(v) ? v.length > 0 : Boolean(v)
|
|
2264
|
+
);
|
|
2132
2265
|
if (hasCommands) {
|
|
2133
2266
|
if (isMarkdown || isMdc) {
|
|
2134
2267
|
sections.push("## Commands");
|
|
@@ -2139,24 +2272,68 @@ function generateFileContent(options, platform) {
|
|
|
2139
2272
|
} else {
|
|
2140
2273
|
sections.push("Commands:");
|
|
2141
2274
|
}
|
|
2142
|
-
|
|
2143
|
-
|
|
2275
|
+
const cmdCategories = ["build", "test", "lint", "dev", "custom"];
|
|
2276
|
+
for (const cat of cmdCategories) {
|
|
2277
|
+
const cmd = options.commands[cat];
|
|
2278
|
+
if (cmd) {
|
|
2279
|
+
const cmds = Array.isArray(cmd) ? cmd : [cmd];
|
|
2280
|
+
for (const c of cmds) {
|
|
2281
|
+
if (c) {
|
|
2282
|
+
const label = cat.charAt(0).toUpperCase() + cat.slice(1);
|
|
2283
|
+
sections.push(isMarkdown || isMdc ? `# ${label}: ${c}` : `- ${label}: ${c}`);
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2144
2287
|
}
|
|
2145
|
-
if (
|
|
2146
|
-
sections.push(
|
|
2288
|
+
if (isMarkdown || isMdc) {
|
|
2289
|
+
sections.push("```");
|
|
2147
2290
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2291
|
+
sections.push("");
|
|
2292
|
+
}
|
|
2293
|
+
if (options.aiBehavior && options.aiBehavior.length > 0) {
|
|
2294
|
+
if (isMarkdown || isMdc) {
|
|
2295
|
+
sections.push("## AI Behavior Rules");
|
|
2296
|
+
sections.push("");
|
|
2297
|
+
for (const rule of options.aiBehavior) {
|
|
2298
|
+
const desc = AI_BEHAVIOR_DESCRIPTIONS[rule];
|
|
2299
|
+
if (desc) {
|
|
2300
|
+
sections.push(`- ${desc}`);
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
sections.push("");
|
|
2150
2304
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2305
|
+
}
|
|
2306
|
+
if (options.importantFiles && options.importantFiles.length > 0) {
|
|
2307
|
+
if (isMarkdown || isMdc) {
|
|
2308
|
+
sections.push("## Important Files to Read");
|
|
2309
|
+
sections.push("");
|
|
2310
|
+
sections.push("Always read these files first to understand the project context:");
|
|
2311
|
+
sections.push("");
|
|
2312
|
+
for (const file of options.importantFiles) {
|
|
2313
|
+
const path2 = IMPORTANT_FILES_PATHS[file];
|
|
2314
|
+
if (path2) {
|
|
2315
|
+
sections.push(`- \`${path2}\``);
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
sections.push("");
|
|
2153
2319
|
}
|
|
2320
|
+
}
|
|
2321
|
+
if (options.selfImprove) {
|
|
2154
2322
|
if (isMarkdown || isMdc) {
|
|
2155
|
-
sections.push("
|
|
2323
|
+
sections.push("## Self-Improving Blueprint");
|
|
2324
|
+
sections.push("");
|
|
2325
|
+
sections.push("> **Auto-update enabled:** As you work on this project, track patterns and update this configuration file to better reflect the project's conventions and preferences.");
|
|
2326
|
+
sections.push("");
|
|
2156
2327
|
}
|
|
2157
|
-
sections.push("");
|
|
2158
2328
|
}
|
|
2159
|
-
|
|
2329
|
+
let boundaries = BOUNDARIES[options.boundaries];
|
|
2330
|
+
if (options.boundaryNever?.length || options.boundaryAsk?.length) {
|
|
2331
|
+
boundaries = {
|
|
2332
|
+
...boundaries,
|
|
2333
|
+
never: options.boundaryNever?.length ? options.boundaryNever : boundaries.never,
|
|
2334
|
+
askFirst: options.boundaryAsk?.length ? options.boundaryAsk : boundaries.askFirst
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
2160
2337
|
if (boundaries) {
|
|
2161
2338
|
if (isMarkdown || isMdc) {
|
|
2162
2339
|
sections.push("## Boundaries");
|
|
@@ -2201,6 +2378,27 @@ function generateFileContent(options, platform) {
|
|
|
2201
2378
|
if (isMarkdown || isMdc) {
|
|
2202
2379
|
sections.push("## Code Style");
|
|
2203
2380
|
sections.push("");
|
|
2381
|
+
if (options.namingConvention) {
|
|
2382
|
+
const namingDesc = NAMING_DESCRIPTIONS[options.namingConvention];
|
|
2383
|
+
if (namingDesc) {
|
|
2384
|
+
sections.push(`- **Naming:** ${namingDesc}`);
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
if (options.errorHandling) {
|
|
2388
|
+
const errorStyles = {
|
|
2389
|
+
try_catch: "Use try/catch blocks for error handling",
|
|
2390
|
+
result_types: "Use Result/Either types for error handling",
|
|
2391
|
+
error_codes: "Use error codes with proper documentation",
|
|
2392
|
+
exceptions: "Use custom exception classes"
|
|
2393
|
+
};
|
|
2394
|
+
if (errorStyles[options.errorHandling]) {
|
|
2395
|
+
sections.push(`- **Errors:** ${errorStyles[options.errorHandling]}`);
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
if (options.styleNotes) {
|
|
2399
|
+
sections.push(`- **Notes:** ${options.styleNotes}`);
|
|
2400
|
+
}
|
|
2401
|
+
sections.push("");
|
|
2204
2402
|
sections.push("Follow these conventions:");
|
|
2205
2403
|
sections.push("");
|
|
2206
2404
|
if (options.stack.includes("typescript") || options.stack.includes("javascript")) {
|
|
@@ -2234,6 +2432,49 @@ function generateFileContent(options, platform) {
|
|
|
2234
2432
|
sections.push("- Keep functions focused and testable");
|
|
2235
2433
|
sections.push("");
|
|
2236
2434
|
}
|
|
2435
|
+
if (options.testLevels?.length || options.testFrameworks?.length || options.coverageTarget) {
|
|
2436
|
+
if (isMarkdown || isMdc) {
|
|
2437
|
+
sections.push("## Testing Strategy");
|
|
2438
|
+
sections.push("");
|
|
2439
|
+
if (options.testLevels?.length) {
|
|
2440
|
+
sections.push("### Test Levels");
|
|
2441
|
+
sections.push("");
|
|
2442
|
+
for (const level of options.testLevels) {
|
|
2443
|
+
const desc = TEST_LEVEL_DESCRIPTIONS[level];
|
|
2444
|
+
if (desc) {
|
|
2445
|
+
sections.push(`- **${level.charAt(0).toUpperCase() + level.slice(1)}:** ${desc}`);
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
sections.push("");
|
|
2449
|
+
}
|
|
2450
|
+
if (options.testFrameworks?.length) {
|
|
2451
|
+
sections.push("### Frameworks");
|
|
2452
|
+
sections.push("");
|
|
2453
|
+
sections.push(`Use: ${options.testFrameworks.join(", ")}`);
|
|
2454
|
+
sections.push("");
|
|
2455
|
+
}
|
|
2456
|
+
if (options.coverageTarget) {
|
|
2457
|
+
sections.push(`### Coverage Target: ${options.coverageTarget}%`);
|
|
2458
|
+
sections.push("");
|
|
2459
|
+
}
|
|
2460
|
+
if (options.testNotes) {
|
|
2461
|
+
sections.push(`**Notes:** ${options.testNotes}`);
|
|
2462
|
+
sections.push("");
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
if (options.extraNotes) {
|
|
2467
|
+
if (isMarkdown || isMdc) {
|
|
2468
|
+
sections.push("## Additional Notes");
|
|
2469
|
+
sections.push("");
|
|
2470
|
+
sections.push(options.extraNotes);
|
|
2471
|
+
sections.push("");
|
|
2472
|
+
} else {
|
|
2473
|
+
sections.push("Additional Notes:");
|
|
2474
|
+
sections.push(options.extraNotes);
|
|
2475
|
+
sections.push("");
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2237
2478
|
if (isMarkdown || isMdc) {
|
|
2238
2479
|
sections.push("---");
|
|
2239
2480
|
sections.push("");
|
|
@@ -2241,37 +2482,90 @@ function generateFileContent(options, platform) {
|
|
|
2241
2482
|
}
|
|
2242
2483
|
return sections.join("\n");
|
|
2243
2484
|
}
|
|
2485
|
+
function generateYamlConfig(options, platform) {
|
|
2486
|
+
const lines = [];
|
|
2487
|
+
if (platform === "aider") {
|
|
2488
|
+
lines.push("# Aider configuration");
|
|
2489
|
+
lines.push(`# Project: ${options.name}`);
|
|
2490
|
+
lines.push("");
|
|
2491
|
+
lines.push("# Model settings");
|
|
2492
|
+
lines.push("model: gpt-4");
|
|
2493
|
+
lines.push("");
|
|
2494
|
+
lines.push("# Code style");
|
|
2495
|
+
if (options.stack.includes("typescript") || options.stack.includes("javascript")) {
|
|
2496
|
+
lines.push("auto-lint: true");
|
|
2497
|
+
}
|
|
2498
|
+
lines.push("");
|
|
2499
|
+
lines.push("# Custom instructions");
|
|
2500
|
+
lines.push("read:");
|
|
2501
|
+
lines.push(" - README.md");
|
|
2502
|
+
if (options.importantFiles?.includes("architecture")) {
|
|
2503
|
+
lines.push(" - ARCHITECTURE.md");
|
|
2504
|
+
}
|
|
2505
|
+
} else if (platform === "tabnine") {
|
|
2506
|
+
lines.push("# Tabnine configuration");
|
|
2507
|
+
lines.push(`# Project: ${options.name}`);
|
|
2508
|
+
lines.push("");
|
|
2509
|
+
lines.push("version: 1.0.0");
|
|
2510
|
+
lines.push("");
|
|
2511
|
+
lines.push("project:");
|
|
2512
|
+
lines.push(` name: ${options.name}`);
|
|
2513
|
+
if (options.description) {
|
|
2514
|
+
lines.push(` description: "${options.description}"`);
|
|
2515
|
+
}
|
|
2516
|
+
lines.push("");
|
|
2517
|
+
lines.push("context:");
|
|
2518
|
+
lines.push(" include:");
|
|
2519
|
+
lines.push(' - "**/*.ts"');
|
|
2520
|
+
lines.push(' - "**/*.js"');
|
|
2521
|
+
lines.push(' - "**/*.py"');
|
|
2522
|
+
}
|
|
2523
|
+
lines.push("");
|
|
2524
|
+
lines.push(`# Generated by LynxPrompt CLI`);
|
|
2525
|
+
return lines.join("\n");
|
|
2526
|
+
}
|
|
2244
2527
|
|
|
2245
2528
|
// src/commands/wizard.ts
|
|
2529
|
+
var WIZARD_STEPS = [
|
|
2530
|
+
{ id: "format", title: "Output Format", icon: "\u{1F4E4}", tier: "basic" },
|
|
2531
|
+
{ id: "project", title: "Project Basics", icon: "\u2728", tier: "basic" },
|
|
2532
|
+
{ id: "tech", title: "Tech Stack", icon: "\u{1F4BB}", tier: "basic" },
|
|
2533
|
+
{ id: "repo", title: "Repository Setup", icon: "\u{1F500}", tier: "basic" },
|
|
2534
|
+
{ id: "commands", title: "Commands", icon: "\u{1F4CB}", tier: "intermediate" },
|
|
2535
|
+
{ id: "code_style", title: "Code Style", icon: "\u{1FA84}", tier: "intermediate" },
|
|
2536
|
+
{ id: "ai", title: "AI Behavior", icon: "\u{1F9E0}", tier: "basic" },
|
|
2537
|
+
{ id: "boundaries", title: "Boundaries", icon: "\u{1F6E1}\uFE0F", tier: "advanced" },
|
|
2538
|
+
{ id: "testing", title: "Testing Strategy", icon: "\u{1F9EA}", tier: "advanced" },
|
|
2539
|
+
{ id: "static", title: "Static Files", icon: "\u{1F4C4}", tier: "advanced" },
|
|
2540
|
+
{ id: "extra", title: "Final Details", icon: "\u{1F4AC}", tier: "basic" }
|
|
2541
|
+
];
|
|
2542
|
+
var ALL_PLATFORMS = [
|
|
2543
|
+
{ id: "agents", name: "Universal (AGENTS.md)", file: "AGENTS.md", icon: "\u{1F310}", note: "Works with all AI-enabled IDEs" },
|
|
2544
|
+
{ id: "cursor", name: "Cursor", file: ".cursor/rules/", icon: "\u26A1", note: "Native project rules format" },
|
|
2545
|
+
{ id: "claude", name: "Claude Code", file: "CLAUDE.md", icon: "\u{1F9E0}", note: "Also works with Cursor" },
|
|
2546
|
+
{ id: "copilot", name: "GitHub Copilot", file: ".github/copilot-instructions.md", icon: "\u{1F419}", note: "VS Code & JetBrains" },
|
|
2547
|
+
{ id: "windsurf", name: "Windsurf", file: ".windsurfrules", icon: "\u{1F3C4}", note: "Codeium IDE" },
|
|
2548
|
+
{ id: "zed", name: "Zed", file: ".zed/instructions.md", icon: "\u26A1", note: "Zed editor" },
|
|
2549
|
+
{ id: "aider", name: "Aider", file: ".aider.conf.yml", icon: "\u{1F916}", note: "CLI AI pair programming" },
|
|
2550
|
+
{ id: "cline", name: "Cline", file: ".clinerules", icon: "\u{1F527}", note: "VS Code extension" },
|
|
2551
|
+
{ id: "continue", name: "Continue", file: ".continue/config.json", icon: "\u27A1\uFE0F", note: "Open-source autopilot" },
|
|
2552
|
+
{ id: "cody", name: "Sourcegraph Cody", file: ".cody/config.json", icon: "\u{1F50D}", note: "Context-aware AI" },
|
|
2553
|
+
{ id: "amazonq", name: "Amazon Q", file: ".amazonq/rules/", icon: "\u{1F4E6}", note: "AWS AI assistant" },
|
|
2554
|
+
{ id: "tabnine", name: "Tabnine", file: ".tabnine.yaml", icon: "\u{1F4DD}", note: "AI code completion" },
|
|
2555
|
+
{ id: "supermaven", name: "Supermaven", file: ".supermaven/config.json", icon: "\u{1F9B8}", note: "Fast AI completions" },
|
|
2556
|
+
{ id: "codegpt", name: "CodeGPT", file: ".codegpt/config.json", icon: "\u{1F4AC}", note: "VS Code AI assistant" },
|
|
2557
|
+
{ id: "void", name: "Void", file: ".void/config.json", icon: "\u{1F573}\uFE0F", note: "Open-source Cursor alt" },
|
|
2558
|
+
{ id: "goose", name: "Goose", file: ".goosehints", icon: "\u{1FABF}", note: "Block AI agent" }
|
|
2559
|
+
];
|
|
2246
2560
|
var OUTPUT_FORMATS = [
|
|
2247
|
-
{
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
},
|
|
2253
|
-
{
|
|
2254
|
-
title: "\u{1F5B1}\uFE0F Cursor",
|
|
2255
|
-
value: "cursor",
|
|
2256
|
-
description: ".cursor/rules/ with MDC format"
|
|
2257
|
-
},
|
|
2258
|
-
{
|
|
2259
|
-
title: "\u{1F30A} Windsurf",
|
|
2260
|
-
value: "windsurf",
|
|
2261
|
-
description: ".windsurfrules configuration"
|
|
2262
|
-
},
|
|
2263
|
-
{
|
|
2264
|
-
title: "\u{1F916} Claude Code",
|
|
2265
|
-
value: "claude",
|
|
2266
|
-
description: "CLAUDE.md for Claude AI"
|
|
2267
|
-
},
|
|
2268
|
-
{
|
|
2269
|
-
title: "\u{1F4E6} Multiple",
|
|
2270
|
-
value: "multiple",
|
|
2271
|
-
description: "Generate for multiple AI editors"
|
|
2272
|
-
}
|
|
2561
|
+
{ title: "\u{1F310} AGENTS.md (Universal)", value: "agents", description: "Works with Claude, Copilot, Aider, Devin & more", recommended: true },
|
|
2562
|
+
{ title: "\u26A1 Cursor", value: "cursor", description: ".cursor/rules/ native format" },
|
|
2563
|
+
{ title: "\u{1F9E0} Claude Code", value: "claude", description: "CLAUDE.md format" },
|
|
2564
|
+
{ title: "\u{1F419} GitHub Copilot", value: "copilot", description: ".github/copilot-instructions.md" },
|
|
2565
|
+
{ title: "\u{1F3C4} Windsurf", value: "windsurf", description: ".windsurfrules configuration" },
|
|
2566
|
+
{ title: "\u{1F4E6} Multiple platforms...", value: "multiple", description: "Select from 16+ supported AI editors" }
|
|
2273
2567
|
];
|
|
2274
|
-
var
|
|
2568
|
+
var LANGUAGES = [
|
|
2275
2569
|
{ title: "\u{1F537} TypeScript", value: "typescript" },
|
|
2276
2570
|
{ title: "\u{1F7E1} JavaScript", value: "javascript" },
|
|
2277
2571
|
{ title: "\u{1F40D} Python", value: "python" },
|
|
@@ -2281,7 +2575,9 @@ var TECH_STACKS = [
|
|
|
2281
2575
|
{ title: "\u{1F49C} C#/.NET", value: "csharp" },
|
|
2282
2576
|
{ title: "\u{1F48E} Ruby", value: "ruby" },
|
|
2283
2577
|
{ title: "\u{1F418} PHP", value: "php" },
|
|
2284
|
-
{ title: "\u{1F34E} Swift", value: "swift" }
|
|
2578
|
+
{ title: "\u{1F34E} Swift", value: "swift" },
|
|
2579
|
+
{ title: "\u{1F536} Kotlin", value: "kotlin" },
|
|
2580
|
+
{ title: "\u2B1B C/C++", value: "cpp" }
|
|
2285
2581
|
];
|
|
2286
2582
|
var FRAMEWORKS = [
|
|
2287
2583
|
{ title: "\u269B\uFE0F React", value: "react" },
|
|
@@ -2300,23 +2596,133 @@ var FRAMEWORKS = [
|
|
|
2300
2596
|
{ title: "\u26A1 Vite", value: "vite" },
|
|
2301
2597
|
{ title: "\u{1F4F1} React Native", value: "react-native" }
|
|
2302
2598
|
];
|
|
2303
|
-
var
|
|
2304
|
-
{ title: "\u{
|
|
2305
|
-
{ title: "\u{
|
|
2306
|
-
{ title: "\u{
|
|
2307
|
-
{ title: "\u{
|
|
2308
|
-
{ title: "\u{
|
|
2309
|
-
{ title: "\
|
|
2310
|
-
{ title: "\u{
|
|
2599
|
+
var DATABASES = [
|
|
2600
|
+
{ title: "\u{1F418} PostgreSQL", value: "postgresql" },
|
|
2601
|
+
{ title: "\u{1F42C} MySQL", value: "mysql" },
|
|
2602
|
+
{ title: "\u{1F343} MongoDB", value: "mongodb" },
|
|
2603
|
+
{ title: "\u{1F534} Redis", value: "redis" },
|
|
2604
|
+
{ title: "\u{1F4CA} SQLite", value: "sqlite" },
|
|
2605
|
+
{ title: "\u2601\uFE0F Supabase", value: "supabase" },
|
|
2606
|
+
{ title: "\u{1F525} Firebase", value: "firebase" },
|
|
2607
|
+
{ title: "\u{1F4C2} Prisma", value: "prisma" }
|
|
2608
|
+
];
|
|
2609
|
+
var REPO_HOSTS = [
|
|
2610
|
+
{ id: "github", label: "GitHub", icon: "\u{1F419}" },
|
|
2611
|
+
{ id: "gitlab", label: "GitLab", icon: "\u{1F98A}" },
|
|
2612
|
+
{ id: "bitbucket", label: "Bitbucket", icon: "\u{1FAA3}" },
|
|
2613
|
+
{ id: "gitea", label: "Gitea", icon: "\u{1F375}" },
|
|
2614
|
+
{ id: "azure", label: "Azure DevOps", icon: "\u2601\uFE0F" },
|
|
2615
|
+
{ id: "other", label: "Other", icon: "\u{1F4E6}" }
|
|
2616
|
+
];
|
|
2617
|
+
var LICENSES = [
|
|
2618
|
+
{ id: "mit", label: "MIT" },
|
|
2619
|
+
{ id: "apache-2.0", label: "Apache 2.0" },
|
|
2620
|
+
{ id: "gpl-3.0", label: "GPL 3.0" },
|
|
2621
|
+
{ id: "lgpl-3.0", label: "LGPL 3.0" },
|
|
2622
|
+
{ id: "agpl-3.0", label: "AGPL 3.0" },
|
|
2623
|
+
{ id: "bsd-3", label: "BSD 3-Clause" },
|
|
2624
|
+
{ id: "mpl-2.0", label: "MPL 2.0" },
|
|
2625
|
+
{ id: "unlicense", label: "Unlicense" },
|
|
2626
|
+
{ id: "none", label: "None / Proprietary" }
|
|
2627
|
+
];
|
|
2628
|
+
var COMMON_COMMANDS = {
|
|
2629
|
+
build: [
|
|
2630
|
+
"npm run build",
|
|
2631
|
+
"pnpm build",
|
|
2632
|
+
"yarn build",
|
|
2633
|
+
"bun run build",
|
|
2634
|
+
"next build",
|
|
2635
|
+
"vite build",
|
|
2636
|
+
"tsc",
|
|
2637
|
+
"tsc --noEmit",
|
|
2638
|
+
"go build",
|
|
2639
|
+
"cargo build",
|
|
2640
|
+
"cargo build --release",
|
|
2641
|
+
"mvn package",
|
|
2642
|
+
"gradle build",
|
|
2643
|
+
"dotnet build",
|
|
2644
|
+
"docker build -t app .",
|
|
2645
|
+
"docker compose build"
|
|
2646
|
+
],
|
|
2647
|
+
test: [
|
|
2648
|
+
"npm test",
|
|
2649
|
+
"pnpm test",
|
|
2650
|
+
"yarn test",
|
|
2651
|
+
"bun test",
|
|
2652
|
+
"vitest",
|
|
2653
|
+
"vitest run",
|
|
2654
|
+
"jest",
|
|
2655
|
+
"jest --coverage",
|
|
2656
|
+
"pytest",
|
|
2657
|
+
"pytest --cov",
|
|
2658
|
+
"go test ./...",
|
|
2659
|
+
"cargo test",
|
|
2660
|
+
"mvn test",
|
|
2661
|
+
"gradle test",
|
|
2662
|
+
"playwright test",
|
|
2663
|
+
"cypress run"
|
|
2664
|
+
],
|
|
2665
|
+
lint: [
|
|
2666
|
+
"npm run lint",
|
|
2667
|
+
"pnpm lint",
|
|
2668
|
+
"eslint .",
|
|
2669
|
+
"eslint . --fix",
|
|
2670
|
+
"prettier --check .",
|
|
2671
|
+
"prettier --write .",
|
|
2672
|
+
"ruff check",
|
|
2673
|
+
"ruff format",
|
|
2674
|
+
"black .",
|
|
2675
|
+
"flake8",
|
|
2676
|
+
"golangci-lint run",
|
|
2677
|
+
"cargo clippy",
|
|
2678
|
+
"rubocop"
|
|
2679
|
+
],
|
|
2680
|
+
dev: [
|
|
2681
|
+
"npm run dev",
|
|
2682
|
+
"pnpm dev",
|
|
2683
|
+
"yarn dev",
|
|
2684
|
+
"bun run dev",
|
|
2685
|
+
"next dev",
|
|
2686
|
+
"vite",
|
|
2687
|
+
"vite dev",
|
|
2688
|
+
"uvicorn main:app --reload",
|
|
2689
|
+
"flask run",
|
|
2690
|
+
"rails server",
|
|
2691
|
+
"go run .",
|
|
2692
|
+
"cargo run",
|
|
2693
|
+
"dotnet run"
|
|
2694
|
+
]
|
|
2695
|
+
};
|
|
2696
|
+
var NAMING_CONVENTIONS = [
|
|
2697
|
+
{ id: "language_default", label: "Follow language conventions", desc: "Use idiomatic style" },
|
|
2698
|
+
{ id: "camelCase", label: "camelCase", desc: "JavaScript, TypeScript, Java" },
|
|
2699
|
+
{ id: "snake_case", label: "snake_case", desc: "Python, Ruby, Rust, Go" },
|
|
2700
|
+
{ id: "PascalCase", label: "PascalCase", desc: "C#, .NET classes" },
|
|
2701
|
+
{ id: "kebab-case", label: "kebab-case", desc: "CSS, HTML, URLs" }
|
|
2702
|
+
];
|
|
2703
|
+
var ERROR_PATTERNS = [
|
|
2704
|
+
{ id: "try_catch", label: "try/catch blocks" },
|
|
2705
|
+
{ id: "result_types", label: "Result/Either types" },
|
|
2706
|
+
{ id: "error_codes", label: "Error codes" },
|
|
2707
|
+
{ id: "exceptions", label: "Custom exceptions" },
|
|
2708
|
+
{ id: "other", label: "Other" }
|
|
2311
2709
|
];
|
|
2312
|
-
var
|
|
2313
|
-
{
|
|
2314
|
-
{
|
|
2315
|
-
{
|
|
2316
|
-
{
|
|
2317
|
-
{
|
|
2318
|
-
{
|
|
2319
|
-
{
|
|
2710
|
+
var AI_BEHAVIOR_RULES = [
|
|
2711
|
+
{ id: "explain_changes", label: "Explain changes before making them", recommended: true },
|
|
2712
|
+
{ id: "preserve_style", label: "Preserve existing code style", recommended: true },
|
|
2713
|
+
{ id: "minimal_changes", label: "Make minimal, focused changes", recommended: true },
|
|
2714
|
+
{ id: "no_comments", label: "Avoid adding unnecessary comments", recommended: false },
|
|
2715
|
+
{ id: "prefer_simple", label: "Prefer simpler solutions", recommended: true },
|
|
2716
|
+
{ id: "test_first", label: "Write tests before implementation", recommended: false },
|
|
2717
|
+
{ id: "no_console", label: "Remove console.log/print before committing", recommended: false },
|
|
2718
|
+
{ id: "type_strict", label: "Be strict with types (no any/Any)", recommended: false }
|
|
2719
|
+
];
|
|
2720
|
+
var IMPORTANT_FILES = [
|
|
2721
|
+
{ id: "readme", label: "README.md", icon: "\u{1F4D6}" },
|
|
2722
|
+
{ id: "package", label: "package.json / pyproject.toml", icon: "\u{1F4E6}" },
|
|
2723
|
+
{ id: "tsconfig", label: "tsconfig.json / config files", icon: "\u2699\uFE0F" },
|
|
2724
|
+
{ id: "architecture", label: "ARCHITECTURE.md", icon: "\u{1F3D7}\uFE0F" },
|
|
2725
|
+
{ id: "contributing", label: "CONTRIBUTING.md", icon: "\u{1F91D}" }
|
|
2320
2726
|
];
|
|
2321
2727
|
var BOUNDARY_PRESETS = [
|
|
2322
2728
|
{
|
|
@@ -2344,11 +2750,79 @@ var BOUNDARY_PRESETS = [
|
|
|
2344
2750
|
never: ["Modify .env", "Access external APIs without confirmation"]
|
|
2345
2751
|
}
|
|
2346
2752
|
];
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2753
|
+
var BOUNDARY_OPTIONS = [
|
|
2754
|
+
"Delete files",
|
|
2755
|
+
"Create new files",
|
|
2756
|
+
"Rename/move files",
|
|
2757
|
+
"Rewrite large sections",
|
|
2758
|
+
"Refactor architecture",
|
|
2759
|
+
"Change dependencies",
|
|
2760
|
+
"Modify database schema",
|
|
2761
|
+
"Update API contracts",
|
|
2762
|
+
"Touch CI pipelines",
|
|
2763
|
+
"Modify Docker config",
|
|
2764
|
+
"Change environment vars",
|
|
2765
|
+
"Update docs automatically",
|
|
2766
|
+
"Edit README",
|
|
2767
|
+
"Handle secrets/credentials",
|
|
2768
|
+
"Modify auth logic",
|
|
2769
|
+
"Delete failing tests",
|
|
2770
|
+
"Skip tests temporarily"
|
|
2771
|
+
];
|
|
2772
|
+
var TEST_FRAMEWORKS = [
|
|
2773
|
+
"jest",
|
|
2774
|
+
"vitest",
|
|
2775
|
+
"mocha",
|
|
2776
|
+
"ava",
|
|
2777
|
+
"tap",
|
|
2778
|
+
"pytest",
|
|
2779
|
+
"unittest",
|
|
2780
|
+
"nose2",
|
|
2781
|
+
"go test",
|
|
2782
|
+
"testify",
|
|
2783
|
+
"cargo test",
|
|
2784
|
+
"rstest",
|
|
2785
|
+
"junit",
|
|
2786
|
+
"testng",
|
|
2787
|
+
"spock",
|
|
2788
|
+
"rspec",
|
|
2789
|
+
"minitest",
|
|
2790
|
+
"phpunit",
|
|
2791
|
+
"pest",
|
|
2792
|
+
"playwright",
|
|
2793
|
+
"cypress",
|
|
2794
|
+
"puppeteer",
|
|
2795
|
+
"selenium"
|
|
2796
|
+
];
|
|
2797
|
+
var TEST_LEVELS = [
|
|
2798
|
+
{ id: "smoke", label: "Smoke", desc: "Quick sanity checks" },
|
|
2799
|
+
{ id: "unit", label: "Unit", desc: "Individual functions/components" },
|
|
2800
|
+
{ id: "integration", label: "Integration", desc: "Component interactions" },
|
|
2801
|
+
{ id: "e2e", label: "E2E", desc: "Full user flows" }
|
|
2802
|
+
];
|
|
2803
|
+
var PROJECT_TYPES = [
|
|
2804
|
+
{ id: "work", label: "Work", icon: "\u{1F4BC}", description: "Professional/enterprise project" },
|
|
2805
|
+
{ id: "leisure", label: "Leisure", icon: "\u{1F3AE}", description: "Personal/hobby project" },
|
|
2806
|
+
{ id: "opensource", label: "Open Source", icon: "\u{1F30D}", description: "Community-driven project" },
|
|
2807
|
+
{ id: "learning", label: "Learning", icon: "\u{1F4DA}", description: "Educational/experimental" }
|
|
2808
|
+
];
|
|
2809
|
+
function canAccessTier(userTier, requiredTier) {
|
|
2810
|
+
const tierLevels = { free: 0, pro: 1, max: 2, teams: 2 };
|
|
2811
|
+
const requiredLevels = { basic: 0, intermediate: 1, advanced: 2 };
|
|
2812
|
+
return tierLevels[userTier] >= requiredLevels[requiredTier];
|
|
2813
|
+
}
|
|
2814
|
+
function getTierBadge(tier) {
|
|
2815
|
+
switch (tier) {
|
|
2816
|
+
case "intermediate":
|
|
2817
|
+
return { label: "PRO", color: chalk8.cyan };
|
|
2818
|
+
case "advanced":
|
|
2819
|
+
return { label: "MAX", color: chalk8.magenta };
|
|
2820
|
+
default:
|
|
2821
|
+
return null;
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
function getAvailableSteps(userTier) {
|
|
2825
|
+
return WIZARD_STEPS.filter((step) => canAccessTier(userTier, step.tier));
|
|
2352
2826
|
}
|
|
2353
2827
|
function printBox(lines, color = chalk8.gray) {
|
|
2354
2828
|
const maxLen = Math.max(...lines.map((l) => l.replace(/\x1b\[[0-9;]*m/g, "").length));
|
|
@@ -2362,11 +2836,83 @@ function printBox(lines, color = chalk8.gray) {
|
|
|
2362
2836
|
}
|
|
2363
2837
|
console.log(color(bottom));
|
|
2364
2838
|
}
|
|
2839
|
+
function showStep(current, step, userTier) {
|
|
2840
|
+
const availableSteps = getAvailableSteps(userTier);
|
|
2841
|
+
const total = availableSteps.length;
|
|
2842
|
+
const progress = "\u25CF".repeat(current) + "\u25CB".repeat(total - current);
|
|
2843
|
+
const badge = getTierBadge(step.tier);
|
|
2844
|
+
console.log();
|
|
2845
|
+
let stepLine = chalk8.cyan(` ${progress} Step ${current}/${total}: ${step.icon} ${step.title}`);
|
|
2846
|
+
if (badge) {
|
|
2847
|
+
stepLine += " " + badge.color(`[${badge.label}]`);
|
|
2848
|
+
}
|
|
2849
|
+
console.log(stepLine);
|
|
2850
|
+
console.log();
|
|
2851
|
+
}
|
|
2852
|
+
function showWizardOverview(userTier) {
|
|
2853
|
+
console.log(chalk8.bold(" \u{1F4CB} Wizard Steps Overview:"));
|
|
2854
|
+
console.log();
|
|
2855
|
+
let stepNum = 1;
|
|
2856
|
+
for (const step of WIZARD_STEPS) {
|
|
2857
|
+
const canAccess = canAccessTier(userTier, step.tier);
|
|
2858
|
+
const badge = getTierBadge(step.tier);
|
|
2859
|
+
if (canAccess) {
|
|
2860
|
+
let line = chalk8.green(` ${stepNum.toString().padStart(2)}. \u2713 ${step.icon} ${step.title}`);
|
|
2861
|
+
if (badge) {
|
|
2862
|
+
line += " " + badge.color(`[${badge.label}]`);
|
|
2863
|
+
}
|
|
2864
|
+
console.log(line);
|
|
2865
|
+
stepNum++;
|
|
2866
|
+
} else {
|
|
2867
|
+
let line = chalk8.gray(` \u2500 \u{1F512} ${step.icon} ${step.title}`);
|
|
2868
|
+
if (badge) {
|
|
2869
|
+
line += " " + badge.color.dim(`[${badge.label}]`);
|
|
2870
|
+
}
|
|
2871
|
+
console.log(line);
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
console.log();
|
|
2875
|
+
}
|
|
2876
|
+
var promptConfig = {
|
|
2877
|
+
onCancel: () => {
|
|
2878
|
+
console.log(chalk8.yellow("\n Cancelled. Run 'lynxp wizard' anytime to restart.\n"));
|
|
2879
|
+
process.exit(0);
|
|
2880
|
+
}
|
|
2881
|
+
};
|
|
2365
2882
|
async function wizardCommand(options) {
|
|
2366
2883
|
console.log();
|
|
2367
2884
|
console.log(chalk8.cyan.bold(" \u{1F431} LynxPrompt Wizard"));
|
|
2368
2885
|
console.log(chalk8.gray(" Generate AI IDE configuration in seconds"));
|
|
2369
2886
|
console.log();
|
|
2887
|
+
const authenticated = isAuthenticated();
|
|
2888
|
+
const user = getUser();
|
|
2889
|
+
const userPlanRaw = user?.plan?.toLowerCase() || "free";
|
|
2890
|
+
const userTier = ["pro", "max", "teams"].includes(userPlanRaw) ? userPlanRaw : "free";
|
|
2891
|
+
const userPlanDisplay = user?.plan?.toUpperCase() || "FREE";
|
|
2892
|
+
if (!authenticated) {
|
|
2893
|
+
console.log(chalk8.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
2894
|
+
console.log(chalk8.yellow("\u2502") + chalk8.white(" \u{1F4A1} ") + chalk8.gray("Log in for full wizard features:") + " " + chalk8.yellow("\u2502"));
|
|
2895
|
+
console.log(chalk8.yellow("\u2502") + " " + chalk8.yellow("\u2502"));
|
|
2896
|
+
console.log(chalk8.yellow("\u2502") + chalk8.gray(" \u2022 ") + chalk8.white("Commands & Code Style") + chalk8.cyan(" [PRO]") + " " + chalk8.yellow("\u2502"));
|
|
2897
|
+
console.log(chalk8.yellow("\u2502") + chalk8.gray(" \u2022 ") + chalk8.white("Boundaries, Testing, Static Files") + chalk8.magenta(" [MAX]") + " " + chalk8.yellow("\u2502"));
|
|
2898
|
+
console.log(chalk8.yellow("\u2502") + chalk8.gray(" \u2022 ") + chalk8.white("Push configs to cloud") + chalk8.gray(" (lynxp push)") + " " + chalk8.yellow("\u2502"));
|
|
2899
|
+
console.log(chalk8.yellow("\u2502") + chalk8.gray(" \u2022 ") + chalk8.white("Sync across devices") + chalk8.gray(" (lynxp sync)") + " " + chalk8.yellow("\u2502"));
|
|
2900
|
+
console.log(chalk8.yellow("\u2502") + " " + chalk8.yellow("\u2502"));
|
|
2901
|
+
console.log(chalk8.yellow("\u2502") + chalk8.cyan(" Run: lynxp login") + " " + chalk8.yellow("\u2502"));
|
|
2902
|
+
console.log(chalk8.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
2903
|
+
console.log();
|
|
2904
|
+
} else {
|
|
2905
|
+
const planEmoji = userTier === "teams" ? "\u{1F465}" : userTier === "max" ? "\u{1F680}" : userTier === "pro" ? "\u26A1" : "\u{1F193}";
|
|
2906
|
+
console.log(chalk8.green(` \u2713 Logged in as ${chalk8.bold(user?.name || user?.email)} ${planEmoji} ${chalk8.gray(userPlanDisplay)}`));
|
|
2907
|
+
console.log();
|
|
2908
|
+
}
|
|
2909
|
+
showWizardOverview(userTier);
|
|
2910
|
+
const accessibleSteps = getAvailableSteps(userTier);
|
|
2911
|
+
const lockedSteps = WIZARD_STEPS.length - accessibleSteps.length;
|
|
2912
|
+
if (lockedSteps > 0) {
|
|
2913
|
+
console.log(chalk8.gray(` ${lockedSteps} step${lockedSteps > 1 ? "s" : ""} locked. Upgrade at ${chalk8.cyan("https://lynxprompt.com/pricing")}`));
|
|
2914
|
+
console.log();
|
|
2915
|
+
}
|
|
2370
2916
|
const detected = await detectProject(process.cwd());
|
|
2371
2917
|
if (detected) {
|
|
2372
2918
|
const detectedInfo = [
|
|
@@ -2398,7 +2944,7 @@ async function wizardCommand(options) {
|
|
|
2398
2944
|
commands: detected?.commands || {}
|
|
2399
2945
|
};
|
|
2400
2946
|
} else {
|
|
2401
|
-
config2 = await runInteractiveWizard(options, detected);
|
|
2947
|
+
config2 = await runInteractiveWizard(options, detected, userTier);
|
|
2402
2948
|
}
|
|
2403
2949
|
const spinner = ora7("Generating configuration...").start();
|
|
2404
2950
|
try {
|
|
@@ -2435,14 +2981,21 @@ async function wizardCommand(options) {
|
|
|
2435
2981
|
console.log(` ${chalk8.cyan("\u2192")} ${chalk8.bold(filename)}`);
|
|
2436
2982
|
}
|
|
2437
2983
|
console.log();
|
|
2438
|
-
|
|
2984
|
+
const nextStepsLines = [
|
|
2439
2985
|
chalk8.gray("Your AI assistant will now follow these instructions."),
|
|
2440
2986
|
"",
|
|
2441
2987
|
chalk8.gray("Next steps:"),
|
|
2442
|
-
chalk8.cyan(" lynxp check ") + chalk8.gray("Validate configuration")
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2988
|
+
chalk8.cyan(" lynxp check ") + chalk8.gray("Validate configuration")
|
|
2989
|
+
];
|
|
2990
|
+
if (authenticated) {
|
|
2991
|
+
nextStepsLines.push(chalk8.cyan(" lynxp push ") + chalk8.gray("Upload to cloud"));
|
|
2992
|
+
nextStepsLines.push(chalk8.cyan(" lynxp link ") + chalk8.gray("Link to a blueprint"));
|
|
2993
|
+
nextStepsLines.push(chalk8.cyan(" lynxp sync ") + chalk8.gray("Sync with linked blueprint"));
|
|
2994
|
+
} else {
|
|
2995
|
+
nextStepsLines.push(chalk8.gray(" lynxp login ") + chalk8.yellow("Log in to push & sync"));
|
|
2996
|
+
}
|
|
2997
|
+
nextStepsLines.push(chalk8.cyan(" lynxp status ") + chalk8.gray("View current setup"));
|
|
2998
|
+
printBox(nextStepsLines, chalk8.gray);
|
|
2446
2999
|
console.log();
|
|
2447
3000
|
} catch (error) {
|
|
2448
3001
|
spinner.fail("Failed to generate files");
|
|
@@ -2454,16 +3007,20 @@ async function wizardCommand(options) {
|
|
|
2454
3007
|
process.exit(1);
|
|
2455
3008
|
}
|
|
2456
3009
|
}
|
|
2457
|
-
async function runInteractiveWizard(options, detected) {
|
|
3010
|
+
async function runInteractiveWizard(options, detected, userTier) {
|
|
2458
3011
|
const answers = {};
|
|
2459
|
-
const
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
3012
|
+
const availableSteps = getAvailableSteps(userTier);
|
|
3013
|
+
let currentStepNum = 0;
|
|
3014
|
+
const getCurrentStep = (stepId) => {
|
|
3015
|
+
const step = availableSteps.find((s) => s.id === stepId);
|
|
3016
|
+
if (step) {
|
|
3017
|
+
currentStepNum++;
|
|
3018
|
+
return step;
|
|
2464
3019
|
}
|
|
3020
|
+
return null;
|
|
2465
3021
|
};
|
|
2466
|
-
|
|
3022
|
+
const formatStep = getCurrentStep("format");
|
|
3023
|
+
showStep(currentStepNum, formatStep, userTier);
|
|
2467
3024
|
let platforms;
|
|
2468
3025
|
if (options.format) {
|
|
2469
3026
|
platforms = options.format.split(",").map((f) => f.trim());
|
|
@@ -2482,26 +3039,31 @@ async function runInteractiveWizard(options, detected) {
|
|
|
2482
3039
|
hint: chalk8.gray("\u2191\u2193 navigate \u2022 enter select")
|
|
2483
3040
|
}, promptConfig);
|
|
2484
3041
|
if (formatResponse.format === "multiple") {
|
|
3042
|
+
console.log();
|
|
3043
|
+
console.log(chalk8.gray(" Select the AI editors you want to generate config for:"));
|
|
2485
3044
|
console.log();
|
|
2486
3045
|
const platformResponse = await prompts4({
|
|
2487
3046
|
type: "multiselect",
|
|
2488
3047
|
name: "platforms",
|
|
2489
|
-
message: chalk8.white("Select AI editors:"),
|
|
2490
|
-
choices:
|
|
2491
|
-
title: p.
|
|
2492
|
-
value: p.
|
|
3048
|
+
message: chalk8.white("Select AI editors (16 supported):"),
|
|
3049
|
+
choices: ALL_PLATFORMS.map((p) => ({
|
|
3050
|
+
title: `${p.icon} ${p.name}`,
|
|
3051
|
+
value: p.id,
|
|
3052
|
+
description: chalk8.gray(p.note)
|
|
2493
3053
|
})),
|
|
2494
3054
|
hint: chalk8.gray("space select \u2022 a toggle all \u2022 enter confirm"),
|
|
2495
3055
|
min: 1,
|
|
2496
3056
|
instructions: false
|
|
2497
3057
|
}, promptConfig);
|
|
2498
3058
|
platforms = platformResponse.platforms || ["agents"];
|
|
3059
|
+
console.log(chalk8.green(` \u2713 Selected ${platforms.length} platform${platforms.length === 1 ? "" : "s"}`));
|
|
2499
3060
|
} else {
|
|
2500
3061
|
platforms = [formatResponse.format || "agents"];
|
|
2501
3062
|
}
|
|
2502
3063
|
}
|
|
2503
3064
|
answers.platforms = platforms;
|
|
2504
|
-
|
|
3065
|
+
const projectStep = getCurrentStep("project");
|
|
3066
|
+
showStep(currentStepNum, projectStep, userTier);
|
|
2505
3067
|
const nameResponse = await prompts4({
|
|
2506
3068
|
type: "text",
|
|
2507
3069
|
name: "name",
|
|
@@ -2518,18 +3080,30 @@ async function runInteractiveWizard(options, detected) {
|
|
|
2518
3080
|
hint: chalk8.gray("optional - helps AI understand context")
|
|
2519
3081
|
}, promptConfig);
|
|
2520
3082
|
answers.description = descResponse.description || "";
|
|
2521
|
-
|
|
2522
|
-
|
|
3083
|
+
const typeResponse = await prompts4({
|
|
3084
|
+
type: "select",
|
|
3085
|
+
name: "projectType",
|
|
3086
|
+
message: chalk8.white("Project type:"),
|
|
3087
|
+
choices: PROJECT_TYPES.map((t) => ({
|
|
3088
|
+
title: `${t.icon} ${t.label}`,
|
|
3089
|
+
value: t.id,
|
|
3090
|
+
description: chalk8.gray(t.description)
|
|
3091
|
+
})),
|
|
3092
|
+
initial: 0
|
|
3093
|
+
}, promptConfig);
|
|
3094
|
+
answers.projectType = typeResponse.projectType || "work";
|
|
3095
|
+
const techStep = getCurrentStep("tech");
|
|
3096
|
+
showStep(currentStepNum, techStep, userTier);
|
|
3097
|
+
const allStackOptions = [...LANGUAGES, ...FRAMEWORKS, ...DATABASES];
|
|
2523
3098
|
const detectedStackSet = new Set(detected?.stack || []);
|
|
2524
|
-
|
|
2525
|
-
if (preselected.length > 0) {
|
|
3099
|
+
if (detectedStackSet.size > 0) {
|
|
2526
3100
|
console.log(chalk8.gray(` Auto-selected: ${detected?.stack?.join(", ")}`));
|
|
2527
3101
|
console.log();
|
|
2528
3102
|
}
|
|
2529
3103
|
const stackResponse = await prompts4({
|
|
2530
3104
|
type: "multiselect",
|
|
2531
3105
|
name: "stack",
|
|
2532
|
-
message: chalk8.white("
|
|
3106
|
+
message: chalk8.white("Languages, frameworks & databases:"),
|
|
2533
3107
|
choices: allStackOptions.map((s) => ({
|
|
2534
3108
|
title: s.title,
|
|
2535
3109
|
value: s.value,
|
|
@@ -2539,52 +3113,370 @@ async function runInteractiveWizard(options, detected) {
|
|
|
2539
3113
|
instructions: false
|
|
2540
3114
|
}, promptConfig);
|
|
2541
3115
|
answers.stack = stackResponse.stack || [];
|
|
2542
|
-
|
|
3116
|
+
const repoStep = getCurrentStep("repo");
|
|
3117
|
+
showStep(currentStepNum, repoStep, userTier);
|
|
3118
|
+
const repoHostResponse = await prompts4({
|
|
3119
|
+
type: "select",
|
|
3120
|
+
name: "repoHost",
|
|
3121
|
+
message: chalk8.white("Repository host:"),
|
|
3122
|
+
choices: REPO_HOSTS.map((h) => ({
|
|
3123
|
+
title: `${h.icon} ${h.label}`,
|
|
3124
|
+
value: h.id
|
|
3125
|
+
})),
|
|
3126
|
+
initial: 0
|
|
3127
|
+
}, promptConfig);
|
|
3128
|
+
answers.repoHost = repoHostResponse.repoHost || "github";
|
|
3129
|
+
const visibilityResponse = await prompts4({
|
|
3130
|
+
type: "toggle",
|
|
3131
|
+
name: "isPublic",
|
|
3132
|
+
message: chalk8.white("Public repository?"),
|
|
3133
|
+
initial: false,
|
|
3134
|
+
active: "Yes",
|
|
3135
|
+
inactive: "No"
|
|
3136
|
+
}, promptConfig);
|
|
3137
|
+
answers.isPublic = visibilityResponse.isPublic || false;
|
|
3138
|
+
const licenseResponse = await prompts4({
|
|
3139
|
+
type: "select",
|
|
3140
|
+
name: "license",
|
|
3141
|
+
message: chalk8.white("License:"),
|
|
3142
|
+
choices: LICENSES.map((l) => ({
|
|
3143
|
+
title: l.label,
|
|
3144
|
+
value: l.id
|
|
3145
|
+
})),
|
|
3146
|
+
initial: 0
|
|
3147
|
+
}, promptConfig);
|
|
3148
|
+
answers.license = licenseResponse.license || "mit";
|
|
3149
|
+
const conventionalResponse = await prompts4({
|
|
3150
|
+
type: "toggle",
|
|
3151
|
+
name: "conventionalCommits",
|
|
3152
|
+
message: chalk8.white("Use Conventional Commits?"),
|
|
3153
|
+
initial: true,
|
|
3154
|
+
active: "Yes",
|
|
3155
|
+
inactive: "No"
|
|
3156
|
+
}, promptConfig);
|
|
3157
|
+
answers.conventionalCommits = conventionalResponse.conventionalCommits ?? true;
|
|
3158
|
+
if (canAccessTier(userTier, "intermediate")) {
|
|
3159
|
+
const commandsStep = getCurrentStep("commands");
|
|
3160
|
+
showStep(currentStepNum, commandsStep, userTier);
|
|
3161
|
+
console.log(chalk8.gray(" Select common commands for your project:"));
|
|
3162
|
+
console.log();
|
|
3163
|
+
const buildResponse = await prompts4({
|
|
3164
|
+
type: "multiselect",
|
|
3165
|
+
name: "build",
|
|
3166
|
+
message: chalk8.white("Build commands:"),
|
|
3167
|
+
choices: COMMON_COMMANDS.build.slice(0, 12).map((c) => ({
|
|
3168
|
+
title: chalk8.cyan(c),
|
|
3169
|
+
value: c,
|
|
3170
|
+
selected: detected?.commands?.build === c
|
|
3171
|
+
})),
|
|
3172
|
+
hint: chalk8.gray("space select \u2022 enter confirm"),
|
|
3173
|
+
instructions: false
|
|
3174
|
+
}, promptConfig);
|
|
3175
|
+
const testResponse = await prompts4({
|
|
3176
|
+
type: "multiselect",
|
|
3177
|
+
name: "test",
|
|
3178
|
+
message: chalk8.white("Test commands:"),
|
|
3179
|
+
choices: COMMON_COMMANDS.test.slice(0, 12).map((c) => ({
|
|
3180
|
+
title: chalk8.yellow(c),
|
|
3181
|
+
value: c,
|
|
3182
|
+
selected: detected?.commands?.test === c
|
|
3183
|
+
})),
|
|
3184
|
+
hint: chalk8.gray("space select \u2022 enter confirm"),
|
|
3185
|
+
instructions: false
|
|
3186
|
+
}, promptConfig);
|
|
3187
|
+
const lintResponse = await prompts4({
|
|
3188
|
+
type: "multiselect",
|
|
3189
|
+
name: "lint",
|
|
3190
|
+
message: chalk8.white("Lint/format commands:"),
|
|
3191
|
+
choices: COMMON_COMMANDS.lint.slice(0, 12).map((c) => ({
|
|
3192
|
+
title: chalk8.green(c),
|
|
3193
|
+
value: c,
|
|
3194
|
+
selected: detected?.commands?.lint === c
|
|
3195
|
+
})),
|
|
3196
|
+
hint: chalk8.gray("space select \u2022 enter confirm"),
|
|
3197
|
+
instructions: false
|
|
3198
|
+
}, promptConfig);
|
|
3199
|
+
const devResponse = await prompts4({
|
|
3200
|
+
type: "multiselect",
|
|
3201
|
+
name: "dev",
|
|
3202
|
+
message: chalk8.white("Dev server commands:"),
|
|
3203
|
+
choices: COMMON_COMMANDS.dev.slice(0, 12).map((c) => ({
|
|
3204
|
+
title: chalk8.magenta(c),
|
|
3205
|
+
value: c,
|
|
3206
|
+
selected: detected?.commands?.dev === c
|
|
3207
|
+
})),
|
|
3208
|
+
hint: chalk8.gray("space select \u2022 enter confirm"),
|
|
3209
|
+
instructions: false
|
|
3210
|
+
}, promptConfig);
|
|
3211
|
+
answers.commands = {
|
|
3212
|
+
build: buildResponse.build || [],
|
|
3213
|
+
test: testResponse.test || [],
|
|
3214
|
+
lint: lintResponse.lint || [],
|
|
3215
|
+
dev: devResponse.dev || []
|
|
3216
|
+
};
|
|
3217
|
+
const customCmdResponse = await prompts4({
|
|
3218
|
+
type: "text",
|
|
3219
|
+
name: "custom",
|
|
3220
|
+
message: chalk8.white("Additional custom command (optional):"),
|
|
3221
|
+
hint: chalk8.gray("e.g., npm run migrate, make deploy")
|
|
3222
|
+
}, promptConfig);
|
|
3223
|
+
if (customCmdResponse.custom) {
|
|
3224
|
+
answers.commands.custom = customCmdResponse.custom;
|
|
3225
|
+
}
|
|
3226
|
+
} else {
|
|
3227
|
+
answers.commands = detected?.commands || {};
|
|
3228
|
+
}
|
|
3229
|
+
if (canAccessTier(userTier, "intermediate")) {
|
|
3230
|
+
const styleStep = getCurrentStep("code_style");
|
|
3231
|
+
showStep(currentStepNum, styleStep, userTier);
|
|
3232
|
+
const namingResponse = await prompts4({
|
|
3233
|
+
type: "select",
|
|
3234
|
+
name: "naming",
|
|
3235
|
+
message: chalk8.white("Naming convention:"),
|
|
3236
|
+
choices: NAMING_CONVENTIONS.map((n) => ({
|
|
3237
|
+
title: n.label,
|
|
3238
|
+
value: n.id,
|
|
3239
|
+
description: chalk8.gray(n.desc)
|
|
3240
|
+
})),
|
|
3241
|
+
initial: 0
|
|
3242
|
+
}, promptConfig);
|
|
3243
|
+
answers.namingConvention = namingResponse.naming || "language_default";
|
|
3244
|
+
const errorResponse = await prompts4({
|
|
3245
|
+
type: "select",
|
|
3246
|
+
name: "errorHandling",
|
|
3247
|
+
message: chalk8.white("Error handling pattern:"),
|
|
3248
|
+
choices: ERROR_PATTERNS.map((e) => ({
|
|
3249
|
+
title: e.label,
|
|
3250
|
+
value: e.id
|
|
3251
|
+
})),
|
|
3252
|
+
initial: 0
|
|
3253
|
+
}, promptConfig);
|
|
3254
|
+
answers.errorHandling = errorResponse.errorHandling || "try_catch";
|
|
3255
|
+
const styleNotesResponse = await prompts4({
|
|
3256
|
+
type: "text",
|
|
3257
|
+
name: "styleNotes",
|
|
3258
|
+
message: chalk8.white("Additional style notes (optional):"),
|
|
3259
|
+
hint: chalk8.gray("e.g., prefer named exports, max line length 100")
|
|
3260
|
+
}, promptConfig);
|
|
3261
|
+
answers.styleNotes = styleNotesResponse.styleNotes || "";
|
|
3262
|
+
}
|
|
3263
|
+
const aiStep = getCurrentStep("ai");
|
|
3264
|
+
showStep(currentStepNum, aiStep, userTier);
|
|
3265
|
+
const aiBehaviorResponse = await prompts4({
|
|
3266
|
+
type: "multiselect",
|
|
3267
|
+
name: "aiBehavior",
|
|
3268
|
+
message: chalk8.white("AI behavior rules:"),
|
|
3269
|
+
choices: AI_BEHAVIOR_RULES.map((r) => ({
|
|
3270
|
+
title: r.recommended ? `${r.label} ${chalk8.green("\u2605")}` : r.label,
|
|
3271
|
+
value: r.id,
|
|
3272
|
+
selected: r.recommended
|
|
3273
|
+
})),
|
|
3274
|
+
hint: chalk8.gray("space select \u2022 enter confirm"),
|
|
3275
|
+
instructions: false
|
|
3276
|
+
}, promptConfig);
|
|
3277
|
+
answers.aiBehavior = aiBehaviorResponse.aiBehavior || [];
|
|
3278
|
+
const importantFilesResponse = await prompts4({
|
|
3279
|
+
type: "multiselect",
|
|
3280
|
+
name: "importantFiles",
|
|
3281
|
+
message: chalk8.white("Important files AI should read:"),
|
|
3282
|
+
choices: IMPORTANT_FILES.map((f) => ({
|
|
3283
|
+
title: `${f.icon} ${f.label}`,
|
|
3284
|
+
value: f.id,
|
|
3285
|
+
selected: f.id === "readme" || f.id === "package"
|
|
3286
|
+
})),
|
|
3287
|
+
hint: chalk8.gray("space select \u2022 enter confirm"),
|
|
3288
|
+
instructions: false
|
|
3289
|
+
}, promptConfig);
|
|
3290
|
+
answers.importantFiles = importantFilesResponse.importantFiles || [];
|
|
3291
|
+
const selfImproveResponse = await prompts4({
|
|
3292
|
+
type: "toggle",
|
|
3293
|
+
name: "selfImprove",
|
|
3294
|
+
message: chalk8.white("Enable self-improving blueprint?"),
|
|
3295
|
+
initial: false,
|
|
3296
|
+
active: "Yes",
|
|
3297
|
+
inactive: "No"
|
|
3298
|
+
}, promptConfig);
|
|
3299
|
+
answers.selfImprove = selfImproveResponse.selfImprove || false;
|
|
3300
|
+
if (canAccessTier(userTier, "advanced")) {
|
|
3301
|
+
const boundariesStep = getCurrentStep("boundaries");
|
|
3302
|
+
showStep(currentStepNum, boundariesStep, userTier);
|
|
3303
|
+
const presetResponse = await prompts4({
|
|
3304
|
+
type: "select",
|
|
3305
|
+
name: "boundaryPreset",
|
|
3306
|
+
message: chalk8.white("Boundary preset:"),
|
|
3307
|
+
choices: BOUNDARY_PRESETS.map((b) => ({
|
|
3308
|
+
title: b.title,
|
|
3309
|
+
value: b.value,
|
|
3310
|
+
description: chalk8.gray(b.description)
|
|
3311
|
+
})),
|
|
3312
|
+
initial: 0
|
|
3313
|
+
}, promptConfig);
|
|
3314
|
+
answers.boundaries = presetResponse.boundaryPreset || "standard";
|
|
3315
|
+
const selectedPreset = BOUNDARY_PRESETS.find((b) => b.value === answers.boundaries);
|
|
3316
|
+
if (selectedPreset) {
|
|
3317
|
+
console.log();
|
|
3318
|
+
console.log(chalk8.gray(" Preset details:"));
|
|
3319
|
+
console.log(chalk8.green(` \u2713 Always: ${selectedPreset.always.slice(0, 3).join(", ")}`));
|
|
3320
|
+
console.log(chalk8.yellow(` ? Ask: ${selectedPreset.askFirst.slice(0, 2).join(", ")}`));
|
|
3321
|
+
console.log(chalk8.red(` \u2717 Never: ${selectedPreset.never.slice(0, 2).join(", ")}`));
|
|
3322
|
+
}
|
|
3323
|
+
const customizeResponse = await prompts4({
|
|
3324
|
+
type: "toggle",
|
|
3325
|
+
name: "customize",
|
|
3326
|
+
message: chalk8.white("Customize specific boundaries?"),
|
|
3327
|
+
initial: false,
|
|
3328
|
+
active: "Yes",
|
|
3329
|
+
inactive: "No"
|
|
3330
|
+
}, promptConfig);
|
|
3331
|
+
if (customizeResponse.customize) {
|
|
3332
|
+
console.log();
|
|
3333
|
+
console.log(chalk8.gray(" Select actions AI should NEVER do:"));
|
|
3334
|
+
const neverResponse = await prompts4({
|
|
3335
|
+
type: "multiselect",
|
|
3336
|
+
name: "never",
|
|
3337
|
+
message: chalk8.white("Never allow:"),
|
|
3338
|
+
choices: BOUNDARY_OPTIONS.map((o) => ({
|
|
3339
|
+
title: chalk8.red(o),
|
|
3340
|
+
value: o,
|
|
3341
|
+
selected: selectedPreset?.never.includes(o)
|
|
3342
|
+
})),
|
|
3343
|
+
instructions: false
|
|
3344
|
+
}, promptConfig);
|
|
3345
|
+
answers.boundaryNever = neverResponse.never || [];
|
|
3346
|
+
console.log(chalk8.gray(" Select actions AI should ASK before doing:"));
|
|
3347
|
+
const askResponse = await prompts4({
|
|
3348
|
+
type: "multiselect",
|
|
3349
|
+
name: "ask",
|
|
3350
|
+
message: chalk8.white("Ask first:"),
|
|
3351
|
+
choices: BOUNDARY_OPTIONS.filter((o) => !answers.boundaryNever?.includes(o)).map((o) => ({
|
|
3352
|
+
title: chalk8.yellow(o),
|
|
3353
|
+
value: o,
|
|
3354
|
+
selected: selectedPreset?.askFirst.includes(o)
|
|
3355
|
+
})),
|
|
3356
|
+
instructions: false
|
|
3357
|
+
}, promptConfig);
|
|
3358
|
+
answers.boundaryAsk = askResponse.ask || [];
|
|
3359
|
+
}
|
|
3360
|
+
} else {
|
|
3361
|
+
answers.boundaries = options.boundaries || "standard";
|
|
3362
|
+
}
|
|
3363
|
+
if (canAccessTier(userTier, "advanced")) {
|
|
3364
|
+
const testingStep = getCurrentStep("testing");
|
|
3365
|
+
showStep(currentStepNum, testingStep, userTier);
|
|
3366
|
+
const testLevelsResponse = await prompts4({
|
|
3367
|
+
type: "multiselect",
|
|
3368
|
+
name: "testLevels",
|
|
3369
|
+
message: chalk8.white("Test levels:"),
|
|
3370
|
+
choices: TEST_LEVELS.map((l) => ({
|
|
3371
|
+
title: `${l.label} - ${chalk8.gray(l.desc)}`,
|
|
3372
|
+
value: l.id,
|
|
3373
|
+
selected: l.id === "unit" || l.id === "integration"
|
|
3374
|
+
})),
|
|
3375
|
+
instructions: false
|
|
3376
|
+
}, promptConfig);
|
|
3377
|
+
answers.testLevels = testLevelsResponse.testLevels || [];
|
|
3378
|
+
const detectedFrameworks = answers.stack?.includes("typescript") || answers.stack?.includes("javascript") ? ["jest", "vitest"] : answers.stack?.includes("python") ? ["pytest"] : [];
|
|
3379
|
+
const testFrameworkResponse = await prompts4({
|
|
3380
|
+
type: "multiselect",
|
|
3381
|
+
name: "testFrameworks",
|
|
3382
|
+
message: chalk8.white("Testing frameworks:"),
|
|
3383
|
+
choices: TEST_FRAMEWORKS.slice(0, 16).map((f) => ({
|
|
3384
|
+
title: f,
|
|
3385
|
+
value: f,
|
|
3386
|
+
selected: detectedFrameworks.includes(f)
|
|
3387
|
+
})),
|
|
3388
|
+
hint: chalk8.gray("space select \u2022 enter confirm"),
|
|
3389
|
+
instructions: false
|
|
3390
|
+
}, promptConfig);
|
|
3391
|
+
answers.testFrameworks = testFrameworkResponse.testFrameworks || [];
|
|
3392
|
+
const coverageResponse = await prompts4({
|
|
3393
|
+
type: "number",
|
|
3394
|
+
name: "coverage",
|
|
3395
|
+
message: chalk8.white("Target code coverage (%):"),
|
|
3396
|
+
initial: 80,
|
|
3397
|
+
min: 0,
|
|
3398
|
+
max: 100
|
|
3399
|
+
}, promptConfig);
|
|
3400
|
+
answers.coverageTarget = coverageResponse.coverage ?? 80;
|
|
3401
|
+
const testNotesResponse = await prompts4({
|
|
3402
|
+
type: "text",
|
|
3403
|
+
name: "testNotes",
|
|
3404
|
+
message: chalk8.white("Testing notes (optional):"),
|
|
3405
|
+
hint: chalk8.gray("e.g., run e2e on main only, use msw for mocking")
|
|
3406
|
+
}, promptConfig);
|
|
3407
|
+
answers.testNotes = testNotesResponse.testNotes || "";
|
|
3408
|
+
}
|
|
3409
|
+
if (canAccessTier(userTier, "advanced")) {
|
|
3410
|
+
const staticStep = getCurrentStep("static");
|
|
3411
|
+
showStep(currentStepNum, staticStep, userTier);
|
|
3412
|
+
console.log(chalk8.gray(" Generate additional project files:"));
|
|
3413
|
+
console.log();
|
|
3414
|
+
const staticFilesResponse = await prompts4({
|
|
3415
|
+
type: "multiselect",
|
|
3416
|
+
name: "staticFiles",
|
|
3417
|
+
message: chalk8.white("Include static files:"),
|
|
3418
|
+
choices: [
|
|
3419
|
+
{ title: "\u{1F4DD} .editorconfig", value: "editorconfig", description: chalk8.gray("Consistent code formatting") },
|
|
3420
|
+
{ title: "\u{1F91D} CONTRIBUTING.md", value: "contributing", description: chalk8.gray("Contributor guidelines") },
|
|
3421
|
+
{ title: "\u{1F4DC} CODE_OF_CONDUCT.md", value: "codeOfConduct", description: chalk8.gray("Community standards") },
|
|
3422
|
+
{ title: "\u{1F512} SECURITY.md", value: "security", description: chalk8.gray("Vulnerability reporting") },
|
|
3423
|
+
{ title: "\u{1F5FA}\uFE0F ROADMAP.md", value: "roadmap", description: chalk8.gray("Project roadmap") },
|
|
3424
|
+
{ title: "\u{1F4CB} .gitignore", value: "gitignore", description: chalk8.gray("Git ignore patterns"), selected: true }
|
|
3425
|
+
],
|
|
3426
|
+
hint: chalk8.gray("space select \u2022 enter confirm"),
|
|
3427
|
+
instructions: false
|
|
3428
|
+
}, promptConfig);
|
|
3429
|
+
answers.staticFiles = staticFilesResponse.staticFiles || [];
|
|
3430
|
+
if (answers.repoHost === "github" && answers.isPublic) {
|
|
3431
|
+
const fundingResponse = await prompts4({
|
|
3432
|
+
type: "toggle",
|
|
3433
|
+
name: "funding",
|
|
3434
|
+
message: chalk8.white("Generate FUNDING.yml for GitHub Sponsors?"),
|
|
3435
|
+
initial: false,
|
|
3436
|
+
active: "Yes",
|
|
3437
|
+
inactive: "No"
|
|
3438
|
+
}, promptConfig);
|
|
3439
|
+
answers.includeFunding = fundingResponse.funding || false;
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
const extraStep = getCurrentStep("extra");
|
|
3443
|
+
showStep(currentStepNum, extraStep, userTier);
|
|
2543
3444
|
const personaResponse = await prompts4({
|
|
2544
3445
|
type: "select",
|
|
2545
3446
|
name: "persona",
|
|
2546
|
-
message: chalk8.white("
|
|
2547
|
-
choices:
|
|
2548
|
-
title:
|
|
2549
|
-
value:
|
|
2550
|
-
description: chalk8.gray(
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
3447
|
+
message: chalk8.white("AI assistant persona:"),
|
|
3448
|
+
choices: [
|
|
3449
|
+
{ title: "\u{1F9D1}\u200D\u{1F4BB} Full-Stack Developer", value: "fullstack", description: chalk8.gray("Complete application development") },
|
|
3450
|
+
{ title: "\u2699\uFE0F Backend Developer", value: "backend", description: chalk8.gray("APIs, databases, services") },
|
|
3451
|
+
{ title: "\u{1F3A8} Frontend Developer", value: "frontend", description: chalk8.gray("UI, components, styling") },
|
|
3452
|
+
{ title: "\u{1F680} DevOps Engineer", value: "devops", description: chalk8.gray("Infrastructure, CI/CD") },
|
|
3453
|
+
{ title: "\u{1F4CA} Data Engineer", value: "data", description: chalk8.gray("Pipelines, ETL, analytics") },
|
|
3454
|
+
{ title: "\u{1F512} Security Engineer", value: "security", description: chalk8.gray("Secure code, auditing") },
|
|
3455
|
+
{ title: "\u270F\uFE0F Custom...", value: "custom", description: chalk8.gray("Define your own") }
|
|
3456
|
+
],
|
|
3457
|
+
initial: 0
|
|
2554
3458
|
}, promptConfig);
|
|
2555
3459
|
if (personaResponse.persona === "custom") {
|
|
2556
3460
|
const customPersona = await prompts4({
|
|
2557
3461
|
type: "text",
|
|
2558
3462
|
name: "value",
|
|
2559
3463
|
message: chalk8.white("Describe the custom persona:"),
|
|
2560
|
-
hint: chalk8.gray("e.g., 'ML engineer focused on PyTorch
|
|
3464
|
+
hint: chalk8.gray("e.g., 'ML engineer focused on PyTorch'")
|
|
2561
3465
|
}, promptConfig);
|
|
2562
3466
|
answers.persona = customPersona.value || "fullstack";
|
|
2563
3467
|
} else {
|
|
2564
3468
|
answers.persona = personaResponse.persona || "fullstack";
|
|
2565
3469
|
}
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
choices: BOUNDARY_PRESETS.map((b) => ({
|
|
2572
|
-
title: b.title,
|
|
2573
|
-
value: b.value,
|
|
2574
|
-
description: chalk8.gray(b.description)
|
|
2575
|
-
})),
|
|
2576
|
-
initial: 0,
|
|
2577
|
-
hint: chalk8.gray("\u2191\u2193 navigate \u2022 enter select")
|
|
3470
|
+
const extraNotesResponse = await prompts4({
|
|
3471
|
+
type: "text",
|
|
3472
|
+
name: "extraNotes",
|
|
3473
|
+
message: chalk8.white("Anything else AI should know? (optional):"),
|
|
3474
|
+
hint: chalk8.gray("Special requirements, gotchas, team conventions...")
|
|
2578
3475
|
}, promptConfig);
|
|
2579
|
-
answers.
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
console.log(chalk8.gray(" Always allowed: ") + chalk8.green(selectedBoundary.always.slice(0, 2).join(", ")));
|
|
2584
|
-
console.log(chalk8.gray(" Ask first: ") + chalk8.yellow(selectedBoundary.askFirst.slice(0, 2).join(", ")));
|
|
2585
|
-
console.log(chalk8.gray(" Never: ") + chalk8.red(selectedBoundary.never.slice(0, 2).join(", ")));
|
|
2586
|
-
}
|
|
2587
|
-
answers.commands = detected?.commands || {};
|
|
3476
|
+
answers.extraNotes = extraNotesResponse.extraNotes || "";
|
|
3477
|
+
console.log();
|
|
3478
|
+
console.log(chalk8.green(" \u2705 All steps completed!"));
|
|
3479
|
+
console.log();
|
|
2588
3480
|
return {
|
|
2589
3481
|
name: answers.name,
|
|
2590
3482
|
description: answers.description,
|
|
@@ -2592,7 +3484,28 @@ async function runInteractiveWizard(options, detected) {
|
|
|
2592
3484
|
platforms: answers.platforms,
|
|
2593
3485
|
persona: answers.persona,
|
|
2594
3486
|
boundaries: answers.boundaries,
|
|
2595
|
-
commands: answers.commands
|
|
3487
|
+
commands: typeof answers.commands === "object" ? answers.commands : detected?.commands || {},
|
|
3488
|
+
// Extended config for Pro/Max users
|
|
3489
|
+
projectType: answers.projectType,
|
|
3490
|
+
repoHost: answers.repoHost,
|
|
3491
|
+
isPublic: answers.isPublic,
|
|
3492
|
+
license: answers.license,
|
|
3493
|
+
conventionalCommits: answers.conventionalCommits,
|
|
3494
|
+
namingConvention: answers.namingConvention,
|
|
3495
|
+
errorHandling: answers.errorHandling,
|
|
3496
|
+
styleNotes: answers.styleNotes,
|
|
3497
|
+
aiBehavior: answers.aiBehavior,
|
|
3498
|
+
importantFiles: answers.importantFiles,
|
|
3499
|
+
selfImprove: answers.selfImprove,
|
|
3500
|
+
boundaryNever: answers.boundaryNever,
|
|
3501
|
+
boundaryAsk: answers.boundaryAsk,
|
|
3502
|
+
testLevels: answers.testLevels,
|
|
3503
|
+
testFrameworks: answers.testFrameworks,
|
|
3504
|
+
coverageTarget: answers.coverageTarget,
|
|
3505
|
+
testNotes: answers.testNotes,
|
|
3506
|
+
staticFiles: answers.staticFiles,
|
|
3507
|
+
includeFunding: answers.includeFunding,
|
|
3508
|
+
extraNotes: answers.extraNotes
|
|
2596
3509
|
};
|
|
2597
3510
|
}
|
|
2598
3511
|
|