lynxprompt 0.5.1 → 0.5.3
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 +177 -99
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1885,7 +1885,8 @@ async function detectFromGitHubApi(repoUrl) {
|
|
|
1885
1885
|
type: "application",
|
|
1886
1886
|
repoHost: "github",
|
|
1887
1887
|
repoUrl,
|
|
1888
|
-
license: repoInfo.license?.spdx_id?.toLowerCase()
|
|
1888
|
+
license: repoInfo.license?.spdx_id?.toLowerCase(),
|
|
1889
|
+
isPublicRepo: !repoInfo.private
|
|
1889
1890
|
};
|
|
1890
1891
|
const filesRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/`, {
|
|
1891
1892
|
headers: { "User-Agent": "LynxPrompt-CLI" }
|
|
@@ -1893,6 +1894,36 @@ async function detectFromGitHubApi(repoUrl) {
|
|
|
1893
1894
|
if (!filesRes.ok) return detected;
|
|
1894
1895
|
const files = await filesRes.json();
|
|
1895
1896
|
const fileNames = new Set(files.map((f) => f.name.toLowerCase()));
|
|
1897
|
+
if (fileNames.has("pyproject.toml")) {
|
|
1898
|
+
detected.stack.push("python");
|
|
1899
|
+
const pyprojectRes = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/pyproject.toml`);
|
|
1900
|
+
if (pyprojectRes.ok) {
|
|
1901
|
+
try {
|
|
1902
|
+
const content = await pyprojectRes.text();
|
|
1903
|
+
if (content.includes("fastapi")) detected.stack.push("fastapi");
|
|
1904
|
+
if (content.includes("django")) detected.stack.push("django");
|
|
1905
|
+
if (content.includes("flask")) detected.stack.push("flask");
|
|
1906
|
+
if (content.includes("sqlalchemy")) detected.stack.push("sqlalchemy");
|
|
1907
|
+
if (content.includes("pydantic")) detected.stack.push("pydantic");
|
|
1908
|
+
if (content.includes("pytest")) detected.stack.push("pytest");
|
|
1909
|
+
if (content.includes("ruff")) detected.stack.push("ruff");
|
|
1910
|
+
} catch {
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
} else if (fileNames.has("requirements.txt")) {
|
|
1914
|
+
detected.stack.push("python");
|
|
1915
|
+
const reqRes = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/requirements.txt`);
|
|
1916
|
+
if (reqRes.ok) {
|
|
1917
|
+
try {
|
|
1918
|
+
const content = (await reqRes.text()).toLowerCase();
|
|
1919
|
+
if (content.includes("fastapi")) detected.stack.push("fastapi");
|
|
1920
|
+
if (content.includes("django")) detected.stack.push("django");
|
|
1921
|
+
if (content.includes("flask")) detected.stack.push("flask");
|
|
1922
|
+
if (content.includes("sqlalchemy")) detected.stack.push("sqlalchemy");
|
|
1923
|
+
} catch {
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1896
1927
|
if (fileNames.has("package.json")) {
|
|
1897
1928
|
const pkgRes = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/package.json`);
|
|
1898
1929
|
if (pkgRes.ok) {
|
|
@@ -1924,10 +1955,22 @@ async function detectFromGitHubApi(repoUrl) {
|
|
|
1924
1955
|
}
|
|
1925
1956
|
}
|
|
1926
1957
|
}
|
|
1927
|
-
if (fileNames.has("pyproject.toml") || fileNames.has("requirements.txt")) detected.stack.push("python");
|
|
1928
1958
|
if (fileNames.has("cargo.toml")) detected.stack.push("rust");
|
|
1929
1959
|
if (fileNames.has("go.mod")) detected.stack.push("go");
|
|
1930
1960
|
if (fileNames.has("dockerfile")) detected.hasDocker = true;
|
|
1961
|
+
if (fileNames.has("docker-compose.yml") || fileNames.has("docker-compose.yaml")) {
|
|
1962
|
+
const composeRes = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/docker-compose.yml`);
|
|
1963
|
+
if (composeRes.ok) {
|
|
1964
|
+
try {
|
|
1965
|
+
const content = (await composeRes.text()).toLowerCase();
|
|
1966
|
+
if (content.includes("postgres")) detected.stack.push("postgresql");
|
|
1967
|
+
if (content.includes("mysql")) detected.stack.push("mysql");
|
|
1968
|
+
if (content.includes("mongo")) detected.stack.push("mongodb");
|
|
1969
|
+
if (content.includes("redis")) detected.stack.push("redis");
|
|
1970
|
+
} catch {
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1931
1974
|
if (files.some((f) => f.name === ".github" && f.type === "dir")) {
|
|
1932
1975
|
detected.cicd = "github_actions";
|
|
1933
1976
|
}
|
|
@@ -3516,17 +3559,17 @@ var CICD_OPTIONS = [
|
|
|
3516
3559
|
{ id: "buildkite", label: "Buildkite", icon: "\u{1F9F1}" }
|
|
3517
3560
|
];
|
|
3518
3561
|
var DEPLOYMENT_TARGETS = [
|
|
3519
|
-
{ id: "vercel", label: "Vercel", icon: "\u25B2" },
|
|
3562
|
+
{ id: "vercel", label: "Vercel", icon: "\u25B2 " },
|
|
3520
3563
|
{ id: "netlify", label: "Netlify", icon: "\u{1F310}" },
|
|
3521
|
-
{ id: "aws", label: "AWS", icon: "\u2601\uFE0F" },
|
|
3564
|
+
{ id: "aws", label: "AWS", icon: "\u2601\uFE0F " },
|
|
3522
3565
|
{ id: "gcp", label: "Google Cloud", icon: "\u{1F308}" },
|
|
3523
3566
|
{ id: "azure", label: "Azure", icon: "\u{1F537}" },
|
|
3524
3567
|
{ id: "docker", label: "Docker", icon: "\u{1F433}" },
|
|
3525
|
-
{ id: "kubernetes", label: "Kubernetes", icon: "\u2638\uFE0F" },
|
|
3568
|
+
{ id: "kubernetes", label: "Kubernetes", icon: "\u2638\uFE0F " },
|
|
3526
3569
|
{ id: "heroku", label: "Heroku", icon: "\u{1F7E3}" },
|
|
3527
3570
|
{ id: "digitalocean", label: "DigitalOcean", icon: "\u{1F535}" },
|
|
3528
3571
|
{ id: "railway", label: "Railway", icon: "\u{1F682}" },
|
|
3529
|
-
{ id: "fly", label: "Fly.io", icon: "\u2708\uFE0F" },
|
|
3572
|
+
{ id: "fly", label: "Fly.io", icon: "\u2708\uFE0F " },
|
|
3530
3573
|
{ id: "cloudflare", label: "Cloudflare", icon: "\u{1F536}" }
|
|
3531
3574
|
];
|
|
3532
3575
|
var CONTAINER_REGISTRIES = [
|
|
@@ -3746,7 +3789,7 @@ var COMMON_COMMANDS = {
|
|
|
3746
3789
|
]
|
|
3747
3790
|
};
|
|
3748
3791
|
var NAMING_CONVENTIONS = [
|
|
3749
|
-
{ id: "language_default", label: "Follow language conventions", desc: "Use idiomatic style" },
|
|
3792
|
+
{ id: "language_default", label: "Follow language conventions", desc: "Use idiomatic style (recommended)" },
|
|
3750
3793
|
{ id: "camelCase", label: "camelCase", desc: "JavaScript, TypeScript, Java" },
|
|
3751
3794
|
{ id: "snake_case", label: "snake_case", desc: "Python, Ruby, Rust, Go" },
|
|
3752
3795
|
{ id: "PascalCase", label: "PascalCase", desc: "C#, .NET classes" },
|
|
@@ -3781,11 +3824,11 @@ var AI_BEHAVIOR_RULES = [
|
|
|
3781
3824
|
{ id: "check_for_security_issues", label: "Check for Security Issues", description: "Review for common vulnerabilities", recommended: false }
|
|
3782
3825
|
];
|
|
3783
3826
|
var IMPORTANT_FILES = [
|
|
3784
|
-
{ id: "readme", label: "README.md", icon: "\u{1F4D6}" },
|
|
3785
|
-
{ id: "package", label: "package.json / pyproject.toml", icon: "\u{1F4E6}" },
|
|
3786
|
-
{ id: "tsconfig", label: "tsconfig.json / config files", icon: "\u2699\uFE0F" },
|
|
3787
|
-
{ id: "architecture", label: "ARCHITECTURE.md", icon: "\u{1F3D7}\uFE0F" },
|
|
3788
|
-
{ id: "contributing", label: "CONTRIBUTING.md", icon: "\u{1F91D}" }
|
|
3827
|
+
{ id: "readme", label: "README.md", icon: "\u{1F4D6} " },
|
|
3828
|
+
{ id: "package", label: "package.json / pyproject.toml", icon: "\u{1F4E6} " },
|
|
3829
|
+
{ id: "tsconfig", label: "tsconfig.json / config files", icon: "\u2699\uFE0F " },
|
|
3830
|
+
{ id: "architecture", label: "ARCHITECTURE.md", icon: "\u{1F3D7}\uFE0F " },
|
|
3831
|
+
{ id: "contributing", label: "CONTRIBUTING.md", icon: "\u{1F91D} " }
|
|
3789
3832
|
];
|
|
3790
3833
|
var BOUNDARY_OPTIONS = [
|
|
3791
3834
|
"Delete files",
|
|
@@ -3937,8 +3980,17 @@ var DEV_OS_OPTIONS = [
|
|
|
3937
3980
|
{ id: "linux", label: "Linux", icon: "\u{1F427}" },
|
|
3938
3981
|
{ id: "windows", label: "Windows", icon: "\u{1FA9F}" },
|
|
3939
3982
|
{ id: "wsl", label: "WSL", icon: "\u{1F427}" },
|
|
3940
|
-
{ id: "remote", label: "Remote/SSH", icon: "\u2601\uFE0F" }
|
|
3983
|
+
{ id: "remote", label: "Remote/SSH", icon: "\u2601\uFE0F" },
|
|
3984
|
+
{ id: "devcontainer", label: "Dev Container", icon: "\u{1F4E6}" },
|
|
3985
|
+
{ id: "codespaces", label: "GitHub Codespaces", icon: "\u2601\uFE0F" }
|
|
3941
3986
|
];
|
|
3987
|
+
function detectCurrentOS() {
|
|
3988
|
+
const platform2 = os.platform();
|
|
3989
|
+
if (platform2 === "darwin") return "macos";
|
|
3990
|
+
if (platform2 === "linux") return "linux";
|
|
3991
|
+
if (platform2 === "win32") return "windows";
|
|
3992
|
+
return "";
|
|
3993
|
+
}
|
|
3942
3994
|
var ARCHITECTURE_PATTERNS = [
|
|
3943
3995
|
{ id: "monolith", label: "Monolith" },
|
|
3944
3996
|
{ id: "microservices", label: "Microservices" },
|
|
@@ -3954,17 +4006,16 @@ function canAccessTier(userTier, requiredTier) {
|
|
|
3954
4006
|
const requiredLevels = { basic: 0, intermediate: 1, advanced: 2 };
|
|
3955
4007
|
return tierLevels[userTier] >= requiredLevels[requiredTier];
|
|
3956
4008
|
}
|
|
4009
|
+
function sortSelectedFirst(choices) {
|
|
4010
|
+
return [...choices].sort((a, b) => {
|
|
4011
|
+
if (a.selected && !b.selected) return -1;
|
|
4012
|
+
if (!a.selected && b.selected) return 1;
|
|
4013
|
+
return 0;
|
|
4014
|
+
});
|
|
4015
|
+
}
|
|
3957
4016
|
function canAccessAI(userTier) {
|
|
3958
4017
|
return userTier === "max" || userTier === "teams";
|
|
3959
4018
|
}
|
|
3960
|
-
function getAIShortcutHint() {
|
|
3961
|
-
const platform2 = os.platform();
|
|
3962
|
-
if (platform2 === "darwin") {
|
|
3963
|
-
return "\u2318+I";
|
|
3964
|
-
} else {
|
|
3965
|
-
return "Ctrl+I";
|
|
3966
|
-
}
|
|
3967
|
-
}
|
|
3968
4019
|
async function aiAssist(instruction, existingContent) {
|
|
3969
4020
|
const spinner = ora7("AI is thinking...").start();
|
|
3970
4021
|
try {
|
|
@@ -4523,40 +4574,43 @@ async function runInteractiveWizard(options, detected, userTier) {
|
|
|
4523
4574
|
type: "text",
|
|
4524
4575
|
name: "description",
|
|
4525
4576
|
message: chalk8.white("Brief description:"),
|
|
4526
|
-
initial: options.description || "",
|
|
4527
|
-
hint: chalk8.gray("optional - helps AI understand context")
|
|
4577
|
+
initial: options.description || detected?.description || "",
|
|
4578
|
+
hint: detected?.description ? chalk8.green("(pre-filled from repo About)") : chalk8.gray("optional - helps AI understand context")
|
|
4528
4579
|
}, promptConfig);
|
|
4529
4580
|
answers.description = descResponse.description || "";
|
|
4581
|
+
const isDetectedOpenSource = detected?.isPublicRepo === true;
|
|
4582
|
+
const projectTypeChoices = [
|
|
4583
|
+
{ title: chalk8.gray("\u23ED Skip"), value: "" },
|
|
4584
|
+
...PROJECT_TYPES.map((t) => ({
|
|
4585
|
+
title: t.id === "opensource" && isDetectedOpenSource ? `${t.icon} ${t.label} ${chalk8.green("(detected)")}` : `${t.icon} ${t.label}`,
|
|
4586
|
+
value: t.id,
|
|
4587
|
+
description: chalk8.gray(t.description)
|
|
4588
|
+
}))
|
|
4589
|
+
];
|
|
4590
|
+
const defaultProjectTypeIdx = isDetectedOpenSource ? projectTypeChoices.findIndex((c) => c.value === "opensource") : 0;
|
|
4530
4591
|
const typeResponse = await prompts4({
|
|
4531
4592
|
type: "select",
|
|
4532
4593
|
name: "projectType",
|
|
4533
4594
|
message: chalk8.white("Project type:"),
|
|
4534
|
-
choices:
|
|
4535
|
-
|
|
4536
|
-
...PROJECT_TYPES.map((t) => ({
|
|
4537
|
-
title: `${t.icon} ${t.label}`,
|
|
4538
|
-
value: t.id,
|
|
4539
|
-
description: chalk8.gray(t.description)
|
|
4540
|
-
}))
|
|
4541
|
-
],
|
|
4542
|
-
initial: 0
|
|
4595
|
+
choices: projectTypeChoices,
|
|
4596
|
+
initial: defaultProjectTypeIdx > 0 ? defaultProjectTypeIdx : 0
|
|
4543
4597
|
}, promptConfig);
|
|
4544
4598
|
answers.projectType = typeResponse.projectType || "";
|
|
4599
|
+
const currentOS = detectCurrentOS();
|
|
4545
4600
|
const devOsResponse = await prompts4({
|
|
4546
|
-
type: "
|
|
4601
|
+
type: "autocompleteMultiselect",
|
|
4547
4602
|
name: "devOS",
|
|
4548
|
-
message: chalk8.white("Development environment:"),
|
|
4549
|
-
choices:
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
hint: chalk8.gray("Helps generate compatible commands")
|
|
4603
|
+
message: chalk8.white("Development environment(s) (type to search):"),
|
|
4604
|
+
choices: DEV_OS_OPTIONS.map((o) => ({
|
|
4605
|
+
title: `${o.icon} ${o.label}`,
|
|
4606
|
+
value: o.id,
|
|
4607
|
+
selected: o.id === currentOS
|
|
4608
|
+
// Pre-select current OS
|
|
4609
|
+
})),
|
|
4610
|
+
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4611
|
+
instructions: false
|
|
4558
4612
|
}, promptConfig);
|
|
4559
|
-
answers.devOS = devOsResponse.devOS ||
|
|
4613
|
+
answers.devOS = devOsResponse.devOS || [];
|
|
4560
4614
|
const archResponse = await prompts4({
|
|
4561
4615
|
type: "select",
|
|
4562
4616
|
name: "architecture",
|
|
@@ -4616,41 +4670,44 @@ async function runInteractiveWizard(options, detected, userTier) {
|
|
|
4616
4670
|
console.log(chalk8.green(` \u2713 Detected in project: ${detected.stack.join(", ")}`));
|
|
4617
4671
|
console.log();
|
|
4618
4672
|
}
|
|
4673
|
+
const languageChoices = sortSelectedFirst(LANGUAGES.map((s) => ({
|
|
4674
|
+
title: s.title,
|
|
4675
|
+
value: s.value,
|
|
4676
|
+
selected: detected?.stack?.includes(s.value)
|
|
4677
|
+
})));
|
|
4619
4678
|
const languageResponse = await prompts4({
|
|
4620
4679
|
type: "autocompleteMultiselect",
|
|
4621
4680
|
name: "languages",
|
|
4622
4681
|
message: chalk8.white("Languages (type to search):"),
|
|
4623
|
-
choices:
|
|
4624
|
-
title: s.title,
|
|
4625
|
-
value: s.value,
|
|
4626
|
-
selected: detected?.stack?.includes(s.value)
|
|
4627
|
-
})),
|
|
4682
|
+
choices: languageChoices,
|
|
4628
4683
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4629
4684
|
instructions: false
|
|
4630
4685
|
}, promptConfig);
|
|
4631
4686
|
const selectedLanguages = languageResponse.languages || [];
|
|
4687
|
+
const frameworkChoices = sortSelectedFirst(FRAMEWORKS.map((s) => ({
|
|
4688
|
+
title: s.title,
|
|
4689
|
+
value: s.value,
|
|
4690
|
+
selected: detected?.stack?.includes(s.value)
|
|
4691
|
+
})));
|
|
4632
4692
|
const frameworkResponse = await prompts4({
|
|
4633
4693
|
type: "autocompleteMultiselect",
|
|
4634
4694
|
name: "frameworks",
|
|
4635
4695
|
message: chalk8.white("Frameworks (type to search):"),
|
|
4636
|
-
choices:
|
|
4637
|
-
title: s.title,
|
|
4638
|
-
value: s.value,
|
|
4639
|
-
selected: detected?.stack?.includes(s.value)
|
|
4640
|
-
})),
|
|
4696
|
+
choices: frameworkChoices,
|
|
4641
4697
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4642
4698
|
instructions: false
|
|
4643
4699
|
}, promptConfig);
|
|
4644
4700
|
const selectedFrameworks = frameworkResponse.frameworks || [];
|
|
4701
|
+
const databaseChoices = sortSelectedFirst(DATABASES.map((s) => ({
|
|
4702
|
+
title: s.title,
|
|
4703
|
+
value: s.value,
|
|
4704
|
+
selected: detected?.stack?.includes(s.value)
|
|
4705
|
+
})));
|
|
4645
4706
|
const databaseResponse = await prompts4({
|
|
4646
4707
|
type: "autocompleteMultiselect",
|
|
4647
4708
|
name: "databases",
|
|
4648
4709
|
message: chalk8.white("Databases (type to search):"),
|
|
4649
|
-
choices:
|
|
4650
|
-
title: s.title,
|
|
4651
|
-
value: s.value,
|
|
4652
|
-
selected: detected?.stack?.includes(s.value)
|
|
4653
|
-
})),
|
|
4710
|
+
choices: databaseChoices,
|
|
4654
4711
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4655
4712
|
instructions: false
|
|
4656
4713
|
}, promptConfig);
|
|
@@ -4755,28 +4812,31 @@ async function runInteractiveWizard(options, detected, userTier) {
|
|
|
4755
4812
|
initial: detectedCicdIndex > 0 ? detectedCicdIndex : 0
|
|
4756
4813
|
}, promptConfig);
|
|
4757
4814
|
answers.cicd = cicdResponse.cicd || "";
|
|
4815
|
+
const deployChoices = sortSelectedFirst(DEPLOYMENT_TARGETS.map((t) => ({
|
|
4816
|
+
title: t.id === "docker" && detected?.hasDocker ? `${t.icon}${t.label} ${chalk8.green("(detected)")}` : `${t.icon}${t.label}`,
|
|
4817
|
+
selected: t.id === "docker" && detected?.hasDocker,
|
|
4818
|
+
value: t.id
|
|
4819
|
+
})));
|
|
4758
4820
|
const deployResponse = await prompts4({
|
|
4759
4821
|
type: "autocompleteMultiselect",
|
|
4760
4822
|
name: "deploymentTargets",
|
|
4761
4823
|
message: chalk8.white("Deployment targets (type to search):"),
|
|
4762
|
-
choices:
|
|
4763
|
-
title: t.id === "docker" && detected?.hasDocker ? `${t.icon} ${t.label} ${chalk8.green("(detected)")}` : `${t.icon} ${t.label}`,
|
|
4764
|
-
selected: t.id === "docker" && detected?.hasDocker,
|
|
4765
|
-
value: t.id
|
|
4766
|
-
})),
|
|
4824
|
+
choices: deployChoices,
|
|
4767
4825
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4768
4826
|
instructions: false
|
|
4769
4827
|
}, promptConfig);
|
|
4770
4828
|
answers.deploymentTargets = deployResponse.deploymentTargets || [];
|
|
4829
|
+
const dockerSelected = (answers.deploymentTargets || []).includes("docker");
|
|
4771
4830
|
const containerResponse = await prompts4({
|
|
4772
4831
|
type: "toggle",
|
|
4773
4832
|
name: "buildContainer",
|
|
4774
4833
|
message: chalk8.white("Build container images (Docker)?"),
|
|
4775
|
-
initial:
|
|
4834
|
+
initial: dockerSelected,
|
|
4835
|
+
// Default Yes if Docker selected
|
|
4776
4836
|
active: "Yes",
|
|
4777
4837
|
inactive: "No"
|
|
4778
4838
|
}, promptConfig);
|
|
4779
|
-
answers.buildContainer = containerResponse.buildContainer
|
|
4839
|
+
answers.buildContainer = containerResponse.buildContainer ?? dockerSelected;
|
|
4780
4840
|
if (answers.buildContainer) {
|
|
4781
4841
|
const registryResponse = await prompts4({
|
|
4782
4842
|
type: "select",
|
|
@@ -4792,6 +4852,16 @@ async function runInteractiveWizard(options, detected, userTier) {
|
|
|
4792
4852
|
initial: 0
|
|
4793
4853
|
}, promptConfig);
|
|
4794
4854
|
answers.containerRegistry = registryResponse.containerRegistry || "";
|
|
4855
|
+
if (answers.containerRegistry === "custom") {
|
|
4856
|
+
const customRegistryResponse = await prompts4({
|
|
4857
|
+
type: "text",
|
|
4858
|
+
name: "customRegistryUrl",
|
|
4859
|
+
message: chalk8.white("Container registry URL:"),
|
|
4860
|
+
hint: chalk8.gray("e.g., registry.example.com:5000"),
|
|
4861
|
+
validate: (v) => v.trim() ? true : "Please enter a registry URL"
|
|
4862
|
+
}, promptConfig);
|
|
4863
|
+
answers.customRegistryUrl = customRegistryResponse.customRegistryUrl || "";
|
|
4864
|
+
}
|
|
4795
4865
|
}
|
|
4796
4866
|
const exampleRepoResponse = await prompts4({
|
|
4797
4867
|
type: "text",
|
|
@@ -4812,51 +4882,55 @@ async function runInteractiveWizard(options, detected, userTier) {
|
|
|
4812
4882
|
showStep(currentStepNum, commandsStep, userTier);
|
|
4813
4883
|
console.log(chalk8.gray(" Select common commands for your project (type to search):"));
|
|
4814
4884
|
console.log();
|
|
4885
|
+
const buildChoices = sortSelectedFirst(COMMON_COMMANDS.build.map((c) => ({
|
|
4886
|
+
title: chalk8.cyan(c),
|
|
4887
|
+
value: c,
|
|
4888
|
+
selected: detected?.commands?.build === c
|
|
4889
|
+
})));
|
|
4815
4890
|
const buildResponse = await prompts4({
|
|
4816
4891
|
type: "autocompleteMultiselect",
|
|
4817
4892
|
name: "build",
|
|
4818
4893
|
message: chalk8.white("Build commands (type to search):"),
|
|
4819
|
-
choices:
|
|
4820
|
-
title: chalk8.cyan(c),
|
|
4821
|
-
value: c,
|
|
4822
|
-
selected: detected?.commands?.build === c
|
|
4823
|
-
})),
|
|
4894
|
+
choices: buildChoices,
|
|
4824
4895
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4825
4896
|
instructions: false
|
|
4826
4897
|
}, promptConfig);
|
|
4898
|
+
const testChoices = sortSelectedFirst(COMMON_COMMANDS.test.map((c) => ({
|
|
4899
|
+
title: chalk8.yellow(c),
|
|
4900
|
+
value: c,
|
|
4901
|
+
selected: detected?.commands?.test === c
|
|
4902
|
+
})));
|
|
4827
4903
|
const testResponse = await prompts4({
|
|
4828
4904
|
type: "autocompleteMultiselect",
|
|
4829
4905
|
name: "test",
|
|
4830
4906
|
message: chalk8.white("Test commands (type to search):"),
|
|
4831
|
-
choices:
|
|
4832
|
-
title: chalk8.yellow(c),
|
|
4833
|
-
value: c,
|
|
4834
|
-
selected: detected?.commands?.test === c
|
|
4835
|
-
})),
|
|
4907
|
+
choices: testChoices,
|
|
4836
4908
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4837
4909
|
instructions: false
|
|
4838
4910
|
}, promptConfig);
|
|
4911
|
+
const lintChoices = sortSelectedFirst(COMMON_COMMANDS.lint.map((c) => ({
|
|
4912
|
+
title: chalk8.green(c),
|
|
4913
|
+
value: c,
|
|
4914
|
+
selected: detected?.commands?.lint === c
|
|
4915
|
+
})));
|
|
4839
4916
|
const lintResponse = await prompts4({
|
|
4840
4917
|
type: "autocompleteMultiselect",
|
|
4841
4918
|
name: "lint",
|
|
4842
4919
|
message: chalk8.white("Lint/format commands (type to search):"),
|
|
4843
|
-
choices:
|
|
4844
|
-
title: chalk8.green(c),
|
|
4845
|
-
value: c,
|
|
4846
|
-
selected: detected?.commands?.lint === c
|
|
4847
|
-
})),
|
|
4920
|
+
choices: lintChoices,
|
|
4848
4921
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4849
4922
|
instructions: false
|
|
4850
4923
|
}, promptConfig);
|
|
4924
|
+
const devChoices = sortSelectedFirst(COMMON_COMMANDS.dev.map((c) => ({
|
|
4925
|
+
title: chalk8.magenta(c),
|
|
4926
|
+
value: c,
|
|
4927
|
+
selected: detected?.commands?.dev === c
|
|
4928
|
+
})));
|
|
4851
4929
|
const devResponse = await prompts4({
|
|
4852
4930
|
type: "autocompleteMultiselect",
|
|
4853
4931
|
name: "dev",
|
|
4854
4932
|
message: chalk8.white("Dev server commands (type to search):"),
|
|
4855
|
-
choices:
|
|
4856
|
-
title: chalk8.magenta(c),
|
|
4857
|
-
value: c,
|
|
4858
|
-
selected: detected?.commands?.dev === c
|
|
4859
|
-
})),
|
|
4933
|
+
choices: devChoices,
|
|
4860
4934
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4861
4935
|
instructions: false
|
|
4862
4936
|
}, promptConfig);
|
|
@@ -4900,12 +4974,13 @@ async function runInteractiveWizard(options, detected, userTier) {
|
|
|
4900
4974
|
choices: [
|
|
4901
4975
|
{ title: chalk8.gray("\u23ED Skip"), value: "" },
|
|
4902
4976
|
...NAMING_CONVENTIONS.map((n) => ({
|
|
4903
|
-
title: n.label,
|
|
4977
|
+
title: n.id === "language_default" ? `${n.label} ${chalk8.green("\u2605 recommended")}` : n.label,
|
|
4904
4978
|
value: n.id,
|
|
4905
4979
|
description: chalk8.gray(n.desc)
|
|
4906
4980
|
}))
|
|
4907
4981
|
],
|
|
4908
|
-
initial:
|
|
4982
|
+
initial: 1
|
|
4983
|
+
// Pre-select "Follow language conventions"
|
|
4909
4984
|
}, promptConfig);
|
|
4910
4985
|
answers.namingConvention = namingResponse.naming || "";
|
|
4911
4986
|
const errorResponse = await prompts4({
|
|
@@ -4969,15 +5044,16 @@ async function runInteractiveWizard(options, detected, userTier) {
|
|
|
4969
5044
|
name: "aiBehavior",
|
|
4970
5045
|
message: chalk8.white("AI behavior rules (type to filter):"),
|
|
4971
5046
|
choices: AI_BEHAVIOR_RULES.map((r) => ({
|
|
4972
|
-
title: r.recommended ? `${r.label} ${chalk8.green("\u2605")}` : r.label,
|
|
5047
|
+
title: r.recommended ? `${r.label} ${chalk8.green("\u2605 recommended")}` : r.label,
|
|
4973
5048
|
value: r.id,
|
|
4974
|
-
description: chalk8.gray(r.description)
|
|
4975
|
-
|
|
5049
|
+
description: chalk8.gray(r.description),
|
|
5050
|
+
selected: true
|
|
5051
|
+
// All selected by default
|
|
4976
5052
|
})),
|
|
4977
5053
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
4978
5054
|
instructions: false
|
|
4979
5055
|
}, promptConfig);
|
|
4980
|
-
answers.aiBehavior = aiBehaviorResponse.aiBehavior ||
|
|
5056
|
+
answers.aiBehavior = aiBehaviorResponse.aiBehavior || AI_BEHAVIOR_RULES.map((r) => r.id);
|
|
4981
5057
|
if (answers.aiBehavior.length > 0) {
|
|
4982
5058
|
console.log(chalk8.green(" \u2713 Selected:"));
|
|
4983
5059
|
for (const ruleId of answers.aiBehavior) {
|
|
@@ -5099,15 +5175,16 @@ async function runInteractiveWizard(options, detected, userTier) {
|
|
|
5099
5175
|
}, promptConfig);
|
|
5100
5176
|
answers.testLevels = testLevelsResponse.testLevels || [];
|
|
5101
5177
|
const detectedFrameworks = answers.stack?.includes("typescript") || answers.stack?.includes("javascript") ? ["jest", "vitest"] : answers.stack?.includes("python") ? ["pytest"] : [];
|
|
5178
|
+
const testFrameworkChoices = sortSelectedFirst(TEST_FRAMEWORKS.map((f) => ({
|
|
5179
|
+
title: f,
|
|
5180
|
+
value: f,
|
|
5181
|
+
selected: detectedFrameworks.includes(f)
|
|
5182
|
+
})));
|
|
5102
5183
|
const testFrameworkResponse = await prompts4({
|
|
5103
5184
|
type: "autocompleteMultiselect",
|
|
5104
5185
|
name: "testFrameworks",
|
|
5105
5186
|
message: chalk8.white("Testing frameworks (type to search):"),
|
|
5106
|
-
choices:
|
|
5107
|
-
title: f,
|
|
5108
|
-
value: f,
|
|
5109
|
-
selected: detectedFrameworks.includes(f)
|
|
5110
|
-
})),
|
|
5187
|
+
choices: testFrameworkChoices,
|
|
5111
5188
|
hint: chalk8.gray("type to filter \u2022 space select \u2022 enter confirm"),
|
|
5112
5189
|
instructions: false
|
|
5113
5190
|
}, promptConfig);
|
|
@@ -5277,8 +5354,9 @@ async function runInteractiveWizard(options, detected, userTier) {
|
|
|
5277
5354
|
const hasAIAccess = canAccessAI(userTier);
|
|
5278
5355
|
if (hasAIAccess) {
|
|
5279
5356
|
console.log();
|
|
5280
|
-
console.log(chalk8.magenta(
|
|
5281
|
-
console.log(chalk8.gray("
|
|
5357
|
+
console.log(chalk8.magenta(" \u2728 AI Assistant available"));
|
|
5358
|
+
console.log(chalk8.gray(" Type 'ai:' followed by your request to get AI-generated content."));
|
|
5359
|
+
console.log(chalk8.gray(" Example: ai: add guidelines for API error handling"));
|
|
5282
5360
|
console.log();
|
|
5283
5361
|
}
|
|
5284
5362
|
const extraNotesResponse = await prompts4({
|