codebakers 3.0.0 → 3.3.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 +811 -176
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
} from "./chunk-HOWR3YTF.js";
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
|
-
import * as
|
|
9
|
+
import * as p8 from "@clack/prompts";
|
|
10
10
|
import ora3 from "ora";
|
|
11
|
-
import
|
|
11
|
+
import fs18 from "fs-extra";
|
|
12
12
|
|
|
13
13
|
// src/core/config.ts
|
|
14
14
|
import Conf from "conf";
|
|
@@ -1285,7 +1285,7 @@ ${originalRequest}`;
|
|
|
1285
1285
|
}
|
|
1286
1286
|
const pathMatch = request.match(/['"`]([^'"`]+)['"`]/g);
|
|
1287
1287
|
if (pathMatch) {
|
|
1288
|
-
keywords.push(...pathMatch.map((
|
|
1288
|
+
keywords.push(...pathMatch.map((p9) => p9.replace(/['"`]/g, "")));
|
|
1289
1289
|
}
|
|
1290
1290
|
return keywords;
|
|
1291
1291
|
}
|
|
@@ -1499,11 +1499,11 @@ Format each as a single line. Be brief.`;
|
|
|
1499
1499
|
} else if (line.toLowerCase().includes("suggestion") || line.toLowerCase().includes("improvement")) {
|
|
1500
1500
|
currentSection = "suggestions";
|
|
1501
1501
|
} else if (line.startsWith("-") || line.startsWith("\u2022") || /^\d+\./.test(line)) {
|
|
1502
|
-
const
|
|
1503
|
-
if (
|
|
1504
|
-
issues.push(
|
|
1505
|
-
} else if (
|
|
1506
|
-
suggestions.push(
|
|
1502
|
+
const text6 = line.replace(/^[-•\d.]\s*/, "").trim();
|
|
1503
|
+
if (text6 && currentSection === "issues") {
|
|
1504
|
+
issues.push(text6);
|
|
1505
|
+
} else if (text6 && currentSection === "suggestions") {
|
|
1506
|
+
suggestions.push(text6);
|
|
1507
1507
|
}
|
|
1508
1508
|
}
|
|
1509
1509
|
}
|
|
@@ -1572,8 +1572,8 @@ Format each as a single line. Be brief.`;
|
|
|
1572
1572
|
if (this.ai) {
|
|
1573
1573
|
onProgress?.("Running AI deep analysis...", 60);
|
|
1574
1574
|
const filesForAI = await Promise.all(
|
|
1575
|
-
filePaths.slice(0, 50).map(async (
|
|
1576
|
-
const f = await this.loadFile(
|
|
1575
|
+
filePaths.slice(0, 50).map(async (p9) => {
|
|
1576
|
+
const f = await this.loadFile(p9);
|
|
1577
1577
|
return f ? { path: f.path, content: f.content } : null;
|
|
1578
1578
|
})
|
|
1579
1579
|
);
|
|
@@ -1729,43 +1729,50 @@ import * as p from "@clack/prompts";
|
|
|
1729
1729
|
// src/utils/ui.ts
|
|
1730
1730
|
import chalk from "chalk";
|
|
1731
1731
|
var colors = {
|
|
1732
|
-
primary: chalk.hex("#
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1732
|
+
primary: chalk.hex("#7fff00"),
|
|
1733
|
+
// Lime green (accent)
|
|
1734
|
+
secondary: chalk.hex("#888888"),
|
|
1735
|
+
// Gray text
|
|
1736
|
+
muted: chalk.hex("#555555"),
|
|
1737
|
+
// Dimmed text
|
|
1738
|
+
success: chalk.hex("#27ae60"),
|
|
1739
|
+
// Green
|
|
1740
|
+
warning: chalk.hex("#f39c12"),
|
|
1741
|
+
// Orange
|
|
1742
|
+
error: chalk.hex("#e74c3c"),
|
|
1743
|
+
// Red
|
|
1744
|
+
info: chalk.hex("#3498db"),
|
|
1745
|
+
// Blue
|
|
1746
|
+
white: chalk.hex("#eeeeee"),
|
|
1747
|
+
dim: chalk.hex("#666666")
|
|
1748
|
+
};
|
|
1749
|
+
var sym = {
|
|
1750
|
+
check: chalk.green("\u2713"),
|
|
1751
|
+
cross: chalk.red("\u2717"),
|
|
1752
|
+
box: chalk.dim("\u2610"),
|
|
1753
|
+
bullet: chalk.dim("\u2022"),
|
|
1754
|
+
arrow: chalk.dim("\u2192"),
|
|
1755
|
+
ellipsis: "\u2026",
|
|
1756
|
+
spinner: "\u27F3"
|
|
1739
1757
|
};
|
|
1740
1758
|
function showHeader() {
|
|
1741
1759
|
console.clear();
|
|
1742
1760
|
console.log("");
|
|
1743
|
-
console.log(colors.
|
|
1744
|
-
console.log(colors.
|
|
1745
|
-
console.log(colors.
|
|
1746
|
-
console.log(colors.
|
|
1747
|
-
console.log("");
|
|
1748
|
-
}
|
|
1749
|
-
function showProjectStatus(name, framework) {
|
|
1750
|
-
console.log(colors.muted(" \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\u2500\u2500\u2500\u2500"));
|
|
1751
|
-
console.log(colors.white(` \u{1F4C1} ${name}`) + colors.muted(` (${framework || "Unknown"})`));
|
|
1752
|
-
console.log(colors.muted(" \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\u2500\u2500\u2500\u2500"));
|
|
1761
|
+
console.log(colors.muted(" \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\u2500\u2500\u2500\u2500\u2510"));
|
|
1762
|
+
console.log(colors.muted(" \u2502") + colors.white(" \u{1F4E6} C O D E B A K E R S ") + colors.muted("\u2502"));
|
|
1763
|
+
console.log(colors.muted(" \u2502") + colors.dim(" ") + colors.muted("\u2502"));
|
|
1764
|
+
console.log(colors.muted(" \u2502") + colors.secondary(" AI Dev Team That Follows The Rules ") + colors.muted("\u2502"));
|
|
1765
|
+
console.log(colors.muted(" \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\u2500\u2500\u2500\u2500\u2518"));
|
|
1753
1766
|
console.log("");
|
|
1754
1767
|
}
|
|
1755
1768
|
function showSuccess(message) {
|
|
1756
|
-
console.log(
|
|
1757
|
-
console.log(colors.success(` \u2705 ${message}`));
|
|
1758
|
-
console.log("");
|
|
1769
|
+
console.log(` ${sym.check} ${colors.white(message)}`);
|
|
1759
1770
|
}
|
|
1760
1771
|
function showError(message) {
|
|
1761
|
-
console.log(
|
|
1762
|
-
console.log(colors.error(` \u274C ${message}`));
|
|
1763
|
-
console.log("");
|
|
1772
|
+
console.log(` ${sym.cross} ${colors.error(message)}`);
|
|
1764
1773
|
}
|
|
1765
1774
|
function showWarning(message) {
|
|
1766
|
-
console.log("");
|
|
1767
|
-
console.log(colors.warning(` \u26A0\uFE0F ${message}`));
|
|
1768
|
-
console.log("");
|
|
1775
|
+
console.log(` ${colors.warning("\u26A0")} ${colors.warning(message)}`);
|
|
1769
1776
|
}
|
|
1770
1777
|
function showInfo(message) {
|
|
1771
1778
|
console.log(colors.muted(` \u2139\uFE0F ${message}`));
|
|
@@ -1774,15 +1781,6 @@ function divider() {
|
|
|
1774
1781
|
console.log(colors.muted(" \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\u2500\u2500\u2500\u2500"));
|
|
1775
1782
|
}
|
|
1776
1783
|
var promptSymbol = colors.primary("\u276F");
|
|
1777
|
-
function showWelcome() {
|
|
1778
|
-
console.log(colors.muted(" Just tell me what you need:"));
|
|
1779
|
-
console.log(colors.muted(' "Add a login page" - Generate code'));
|
|
1780
|
-
console.log(colors.muted(' "Review my code" - Analyze codebase'));
|
|
1781
|
-
console.log(colors.muted(' "Deploy to production" - Ship it'));
|
|
1782
|
-
console.log(colors.muted(' "Undo that" - Rollback'));
|
|
1783
|
-
console.log(colors.muted(" /help - All commands"));
|
|
1784
|
-
console.log("");
|
|
1785
|
-
}
|
|
1786
1784
|
|
|
1787
1785
|
// src/core/nlp.ts
|
|
1788
1786
|
var INTENT_PATTERNS = [
|
|
@@ -2398,7 +2396,11 @@ var NLPInterpreter = class {
|
|
|
2398
2396
|
"account": "whoami",
|
|
2399
2397
|
"me": "whoami",
|
|
2400
2398
|
"index": "index",
|
|
2401
|
-
"rag": "index"
|
|
2399
|
+
"rag": "index",
|
|
2400
|
+
"folder": "folder",
|
|
2401
|
+
"cd": "folder",
|
|
2402
|
+
"chdir": "folder",
|
|
2403
|
+
"browse": "folder"
|
|
2402
2404
|
};
|
|
2403
2405
|
const intent = commandMap[lower] || "unclear";
|
|
2404
2406
|
const params = {};
|
|
@@ -2501,12 +2503,12 @@ var NLPInterpreter = class {
|
|
|
2501
2503
|
deploy: "This will deploy your code. Continue?"
|
|
2502
2504
|
};
|
|
2503
2505
|
console.log("");
|
|
2504
|
-
const
|
|
2506
|
+
const confirm8 = await p.confirm({
|
|
2505
2507
|
message: colors.warning(messages[intent.type] || "Are you sure?"),
|
|
2506
2508
|
initialValue: intent.type !== "deploy"
|
|
2507
2509
|
// Default no for deploy
|
|
2508
2510
|
});
|
|
2509
|
-
return !p.isCancel(
|
|
2511
|
+
return !p.isCancel(confirm8) && confirm8 === true;
|
|
2510
2512
|
}
|
|
2511
2513
|
};
|
|
2512
2514
|
var nlp = new NLPInterpreter();
|
|
@@ -2734,22 +2736,22 @@ Please provide ONLY the corrected file content with the path. No explanation nee
|
|
|
2734
2736
|
// HELPERS
|
|
2735
2737
|
// ============================================================================
|
|
2736
2738
|
async findMissingPackages(packages) {
|
|
2737
|
-
const
|
|
2738
|
-
const
|
|
2739
|
-
const pkgPath =
|
|
2740
|
-
if (!await
|
|
2741
|
-
const pkg = await
|
|
2739
|
+
const fs19 = await import("fs-extra");
|
|
2740
|
+
const path19 = await import("path");
|
|
2741
|
+
const pkgPath = path19.join(this.scanner["projectPath"], "package.json");
|
|
2742
|
+
if (!await fs19.pathExists(pkgPath)) return packages;
|
|
2743
|
+
const pkg = await fs19.readJson(pkgPath);
|
|
2742
2744
|
const installed = {
|
|
2743
2745
|
...pkg.dependencies,
|
|
2744
2746
|
...pkg.devDependencies
|
|
2745
2747
|
};
|
|
2746
|
-
return packages.filter((
|
|
2748
|
+
return packages.filter((p9) => !installed[p9]);
|
|
2747
2749
|
}
|
|
2748
|
-
spin(
|
|
2750
|
+
spin(text6) {
|
|
2749
2751
|
if (this.spinner) {
|
|
2750
|
-
this.spinner.text =
|
|
2752
|
+
this.spinner.text = text6 + " (ESC to cancel)";
|
|
2751
2753
|
} else {
|
|
2752
|
-
this.spinner = ora(
|
|
2754
|
+
this.spinner = ora(text6 + " (ESC to cancel)").start();
|
|
2753
2755
|
}
|
|
2754
2756
|
}
|
|
2755
2757
|
stop() {
|
|
@@ -4067,9 +4069,9 @@ Create ALL files listed above.`;
|
|
|
4067
4069
|
const count = pathMap.get(file.path) || 0;
|
|
4068
4070
|
pathMap.set(file.path, count + 1);
|
|
4069
4071
|
}
|
|
4070
|
-
for (const [
|
|
4072
|
+
for (const [path19, count] of pathMap) {
|
|
4071
4073
|
if (count > 1) {
|
|
4072
|
-
conflicts.push(`Multiple agents created: ${
|
|
4074
|
+
conflicts.push(`Multiple agents created: ${path19}`);
|
|
4073
4075
|
}
|
|
4074
4076
|
}
|
|
4075
4077
|
for (const file of files) {
|
|
@@ -4877,11 +4879,11 @@ var AgentExecutor = class {
|
|
|
4877
4879
|
}
|
|
4878
4880
|
return Array.from(packages);
|
|
4879
4881
|
}
|
|
4880
|
-
spin(
|
|
4882
|
+
spin(text6) {
|
|
4881
4883
|
if (this.spinner) {
|
|
4882
|
-
this.spinner.text =
|
|
4884
|
+
this.spinner.text = text6;
|
|
4883
4885
|
} else {
|
|
4884
|
-
this.spinner = ora2(
|
|
4886
|
+
this.spinner = ora2(text6).start();
|
|
4885
4887
|
}
|
|
4886
4888
|
}
|
|
4887
4889
|
stop() {
|
|
@@ -5186,7 +5188,7 @@ ${chunks[i]}`,
|
|
|
5186
5188
|
projectName: analysis.projectName,
|
|
5187
5189
|
totalFeatures: analysis.features.length,
|
|
5188
5190
|
completedFeatures: analysis.features.filter((f) => f.status === "complete").length,
|
|
5189
|
-
currentPhase: analysis.phases.find((
|
|
5191
|
+
currentPhase: analysis.phases.find((p9) => p9.status === "in_progress")?.id || analysis.phases[0]?.id || "",
|
|
5190
5192
|
currentFeature: analysis.features.find((f) => f.status === "in_progress")?.id || "",
|
|
5191
5193
|
features: analysis.features.map((f) => ({ id: f.id, status: f.status })),
|
|
5192
5194
|
startedAt: Date.now(),
|
|
@@ -6682,8 +6684,8 @@ var SmartGitManager = class {
|
|
|
6682
6684
|
const pr = await this.createPR(phaseBranch, baseBranch);
|
|
6683
6685
|
return pr;
|
|
6684
6686
|
}
|
|
6685
|
-
slugify(
|
|
6686
|
-
return
|
|
6687
|
+
slugify(text6) {
|
|
6688
|
+
return text6.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 30);
|
|
6687
6689
|
}
|
|
6688
6690
|
// ============================================================================
|
|
6689
6691
|
// SMART COMMITS
|
|
@@ -6962,7 +6964,7 @@ var ProjectBuilder = class {
|
|
|
6962
6964
|
totalDuration: 0
|
|
6963
6965
|
};
|
|
6964
6966
|
try {
|
|
6965
|
-
const phaseNames = spec.buildPhases.map((
|
|
6967
|
+
const phaseNames = spec.buildPhases.map((p9) => p9.name.replace(/Phase \d+:\s*/i, ""));
|
|
6966
6968
|
const strategy = await this.git.createProjectStrategy(spec.name, phaseNames);
|
|
6967
6969
|
console.log(this.git.formatStrategy(strategy));
|
|
6968
6970
|
const proceed = await p4.confirm({
|
|
@@ -7669,7 +7671,7 @@ Return ONLY the fixed code, no explanations. Keep all other code exactly the sam
|
|
|
7669
7671
|
return this.patterns;
|
|
7670
7672
|
}
|
|
7671
7673
|
enablePattern(id) {
|
|
7672
|
-
const pattern = this.patterns.find((
|
|
7674
|
+
const pattern = this.patterns.find((p9) => p9.id === id);
|
|
7673
7675
|
if (pattern) {
|
|
7674
7676
|
pattern.enabled = true;
|
|
7675
7677
|
return true;
|
|
@@ -7677,7 +7679,7 @@ Return ONLY the fixed code, no explanations. Keep all other code exactly the sam
|
|
|
7677
7679
|
return false;
|
|
7678
7680
|
}
|
|
7679
7681
|
disablePattern(id) {
|
|
7680
|
-
const pattern = this.patterns.find((
|
|
7682
|
+
const pattern = this.patterns.find((p9) => p9.id === id);
|
|
7681
7683
|
if (pattern) {
|
|
7682
7684
|
pattern.enabled = false;
|
|
7683
7685
|
return true;
|
|
@@ -7736,8 +7738,8 @@ Return ONLY the fixed code, no explanations. Keep all other code exactly the sam
|
|
|
7736
7738
|
formatPatterns() {
|
|
7737
7739
|
let output = "\n";
|
|
7738
7740
|
output += colors.white(" \u{1F4CB} Pattern Rules") + "\n\n";
|
|
7739
|
-
const enabled = this.patterns.filter((
|
|
7740
|
-
const disabled = this.patterns.filter((
|
|
7741
|
+
const enabled = this.patterns.filter((p9) => p9.enabled);
|
|
7742
|
+
const disabled = this.patterns.filter((p9) => !p9.enabled);
|
|
7741
7743
|
output += colors.success(" ENABLED") + "\n";
|
|
7742
7744
|
for (const pattern of enabled) {
|
|
7743
7745
|
const severityIcon = pattern.severity === "critical" ? "\u{1F534}" : pattern.severity === "warning" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
@@ -7762,7 +7764,7 @@ Return ONLY the fixed code, no explanations. Keep all other code exactly the sam
|
|
|
7762
7764
|
return grouped;
|
|
7763
7765
|
}
|
|
7764
7766
|
getPatternName(id) {
|
|
7765
|
-
const pattern = this.patterns.find((
|
|
7767
|
+
const pattern = this.patterns.find((p9) => p9.id === id);
|
|
7766
7768
|
return pattern?.name || id;
|
|
7767
7769
|
}
|
|
7768
7770
|
// ============================================================================
|
|
@@ -7968,7 +7970,7 @@ var SmartSuggestions = class {
|
|
|
7968
7970
|
/platform\s*(that|which|for)/,
|
|
7969
7971
|
/saas\s*(for|that|which)/
|
|
7970
7972
|
];
|
|
7971
|
-
return ideaPatterns.some((
|
|
7973
|
+
return ideaPatterns.some((p9) => p9.test(lower));
|
|
7972
7974
|
}
|
|
7973
7975
|
looksLikeComplexRequest(input) {
|
|
7974
7976
|
const lower = input.toLowerCase();
|
|
@@ -7998,7 +8000,7 @@ var SmartSuggestions = class {
|
|
|
7998
8000
|
/clean\s*up/,
|
|
7999
8001
|
/improve\s*(the\s*)?(code|quality)/
|
|
8000
8002
|
];
|
|
8001
|
-
return patterns.some((
|
|
8003
|
+
return patterns.some((p9) => p9.test(lower));
|
|
8002
8004
|
}
|
|
8003
8005
|
// ============================================================================
|
|
8004
8006
|
// DISPLAY
|
|
@@ -8028,6 +8030,23 @@ var AUTH_STORE = new Conf2({
|
|
|
8028
8030
|
projectName: "codebakers",
|
|
8029
8031
|
encryptionKey: "cb-secure-storage-key-2026"
|
|
8030
8032
|
});
|
|
8033
|
+
var ADMIN_CODES = {
|
|
8034
|
+
"ADMIN-DANIEL-2026": { email: "daniel@botmakers.ai", name: "Daniel" },
|
|
8035
|
+
"ADMIN-BOTMAKERS": { email: "admin@botmakers.ai", name: "Admin" }
|
|
8036
|
+
// Add more admin codes here
|
|
8037
|
+
};
|
|
8038
|
+
var BETA_CODES = {
|
|
8039
|
+
"BETA-TESTER-001": { email: "tester1@beta.com", name: "Beta Tester 1", expiresAt: "2026-12-31" },
|
|
8040
|
+
"BETA-TESTER-002": { email: "tester2@beta.com", name: "Beta Tester 2", expiresAt: "2026-12-31" },
|
|
8041
|
+
"BETA-EARLY-ACCESS": { email: "early@beta.com", name: "Early Access", expiresAt: "2026-06-30" }
|
|
8042
|
+
// Add more beta codes here
|
|
8043
|
+
};
|
|
8044
|
+
var WHITELISTED_EMAILS = [
|
|
8045
|
+
"daniel@botmakers.ai",
|
|
8046
|
+
"admin@botmakers.ai",
|
|
8047
|
+
"team@botmakers.ai"
|
|
8048
|
+
// Add more whitelisted emails here
|
|
8049
|
+
];
|
|
8031
8050
|
var FEATURES = {
|
|
8032
8051
|
// Free features
|
|
8033
8052
|
basic_build: "basic_build",
|
|
@@ -8044,6 +8063,7 @@ var FEATURES = {
|
|
|
8044
8063
|
whitelabel: "whitelabel",
|
|
8045
8064
|
priority_support: "priority_support"
|
|
8046
8065
|
};
|
|
8066
|
+
var ALL_FEATURES = Object.values(FEATURES);
|
|
8047
8067
|
var Auth = class _Auth {
|
|
8048
8068
|
static instance;
|
|
8049
8069
|
constructor() {
|
|
@@ -8055,7 +8075,7 @@ var Auth = class _Auth {
|
|
|
8055
8075
|
return _Auth.instance;
|
|
8056
8076
|
}
|
|
8057
8077
|
// ============================================================================
|
|
8058
|
-
// LOGIN FLOW
|
|
8078
|
+
// LOGIN FLOW - Multiple methods
|
|
8059
8079
|
// ============================================================================
|
|
8060
8080
|
async login() {
|
|
8061
8081
|
const existing = this.getAuth();
|
|
@@ -8071,6 +8091,163 @@ var Auth = class _Auth {
|
|
|
8071
8091
|
console.log("");
|
|
8072
8092
|
console.log(colors.white(" \u{1F510} CodeBakers Login"));
|
|
8073
8093
|
console.log("");
|
|
8094
|
+
const method = await p5.select({
|
|
8095
|
+
message: "How would you like to login?",
|
|
8096
|
+
options: [
|
|
8097
|
+
{ value: "browser", label: "Login with browser (Google/GitHub)" },
|
|
8098
|
+
{ value: "code", label: "Enter admin/beta code" },
|
|
8099
|
+
{ value: "apikey", label: "Use API key only (no account)" }
|
|
8100
|
+
]
|
|
8101
|
+
});
|
|
8102
|
+
if (p5.isCancel(method)) {
|
|
8103
|
+
return false;
|
|
8104
|
+
}
|
|
8105
|
+
switch (method) {
|
|
8106
|
+
case "code":
|
|
8107
|
+
return this.loginWithCode();
|
|
8108
|
+
case "apikey":
|
|
8109
|
+
return this.loginWithApiKey();
|
|
8110
|
+
default:
|
|
8111
|
+
return this.loginWithBrowser();
|
|
8112
|
+
}
|
|
8113
|
+
}
|
|
8114
|
+
// ============================================================================
|
|
8115
|
+
// LOGIN WITH SPECIAL CODE (Admin/Beta)
|
|
8116
|
+
// ============================================================================
|
|
8117
|
+
async loginWithCode() {
|
|
8118
|
+
console.log("");
|
|
8119
|
+
console.log(colors.secondary(" Enter your admin or beta code:"));
|
|
8120
|
+
const code = await p5.text({
|
|
8121
|
+
message: "Code:",
|
|
8122
|
+
placeholder: "ADMIN-XXXX or BETA-XXXX"
|
|
8123
|
+
});
|
|
8124
|
+
if (p5.isCancel(code) || !code) {
|
|
8125
|
+
return false;
|
|
8126
|
+
}
|
|
8127
|
+
const codeUpper = code.toString().toUpperCase().trim();
|
|
8128
|
+
if (ADMIN_CODES[codeUpper]) {
|
|
8129
|
+
const admin = ADMIN_CODES[codeUpper];
|
|
8130
|
+
const auth2 = {
|
|
8131
|
+
accessToken: `admin_${codeUpper}_${Date.now()}`,
|
|
8132
|
+
refreshToken: "",
|
|
8133
|
+
user: {
|
|
8134
|
+
id: `admin_${codeUpper}`,
|
|
8135
|
+
email: admin.email,
|
|
8136
|
+
name: admin.name
|
|
8137
|
+
},
|
|
8138
|
+
license: {
|
|
8139
|
+
tier: "admin",
|
|
8140
|
+
features: ALL_FEATURES,
|
|
8141
|
+
expiresAt: null,
|
|
8142
|
+
// Never expires
|
|
8143
|
+
usage: { current: 0, limit: 999999 }
|
|
8144
|
+
},
|
|
8145
|
+
expiresAt: Date.now() + 365 * 24 * 60 * 60 * 1e3,
|
|
8146
|
+
// 1 year
|
|
8147
|
+
authType: "admin"
|
|
8148
|
+
};
|
|
8149
|
+
this.saveAuth(auth2);
|
|
8150
|
+
console.log("");
|
|
8151
|
+
console.log(colors.success(` \u2713 Logged in as Admin: ${admin.name}`));
|
|
8152
|
+
console.log(colors.muted(" Full access enabled. No expiration."));
|
|
8153
|
+
console.log("");
|
|
8154
|
+
return true;
|
|
8155
|
+
}
|
|
8156
|
+
if (BETA_CODES[codeUpper]) {
|
|
8157
|
+
const beta = BETA_CODES[codeUpper];
|
|
8158
|
+
const expiresAt = new Date(beta.expiresAt);
|
|
8159
|
+
if (expiresAt < /* @__PURE__ */ new Date()) {
|
|
8160
|
+
console.log(colors.error(" \u2717 This beta code has expired."));
|
|
8161
|
+
return false;
|
|
8162
|
+
}
|
|
8163
|
+
const auth2 = {
|
|
8164
|
+
accessToken: `beta_${codeUpper}_${Date.now()}`,
|
|
8165
|
+
refreshToken: "",
|
|
8166
|
+
user: {
|
|
8167
|
+
id: `beta_${codeUpper}`,
|
|
8168
|
+
email: beta.email,
|
|
8169
|
+
name: beta.name
|
|
8170
|
+
},
|
|
8171
|
+
license: {
|
|
8172
|
+
tier: "beta",
|
|
8173
|
+
features: ALL_FEATURES,
|
|
8174
|
+
expiresAt: beta.expiresAt,
|
|
8175
|
+
usage: { current: 0, limit: 999999 }
|
|
8176
|
+
},
|
|
8177
|
+
expiresAt: expiresAt.getTime(),
|
|
8178
|
+
authType: "beta"
|
|
8179
|
+
};
|
|
8180
|
+
this.saveAuth(auth2);
|
|
8181
|
+
console.log("");
|
|
8182
|
+
console.log(colors.success(` \u2713 Logged in as Beta Tester: ${beta.name}`));
|
|
8183
|
+
console.log(colors.muted(` Full access until ${beta.expiresAt}`));
|
|
8184
|
+
console.log("");
|
|
8185
|
+
return true;
|
|
8186
|
+
}
|
|
8187
|
+
console.log(colors.error(" \u2717 Invalid code. Please check and try again."));
|
|
8188
|
+
return false;
|
|
8189
|
+
}
|
|
8190
|
+
// ============================================================================
|
|
8191
|
+
// LOGIN WITH API KEY ONLY (No account needed)
|
|
8192
|
+
// ============================================================================
|
|
8193
|
+
async loginWithApiKey() {
|
|
8194
|
+
console.log("");
|
|
8195
|
+
console.log(colors.secondary(" Using API key only mode."));
|
|
8196
|
+
console.log(colors.muted(" You can use CB without an account."));
|
|
8197
|
+
console.log(colors.muted(" Some features may be limited."));
|
|
8198
|
+
console.log("");
|
|
8199
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
8200
|
+
if (!apiKey) {
|
|
8201
|
+
console.log(colors.warning(" \u26A0 No ANTHROPIC_API_KEY found in environment."));
|
|
8202
|
+
console.log(colors.muted(" Set it with: export ANTHROPIC_API_KEY=your_key"));
|
|
8203
|
+
console.log("");
|
|
8204
|
+
const enterKey = await p5.confirm({
|
|
8205
|
+
message: "Would you like to enter your API key now?",
|
|
8206
|
+
initialValue: true
|
|
8207
|
+
});
|
|
8208
|
+
if (enterKey && !p5.isCancel(enterKey)) {
|
|
8209
|
+
const key = await p5.text({
|
|
8210
|
+
message: "Anthropic API Key:",
|
|
8211
|
+
placeholder: "sk-ant-..."
|
|
8212
|
+
});
|
|
8213
|
+
if (p5.isCancel(key) || !key) {
|
|
8214
|
+
return false;
|
|
8215
|
+
}
|
|
8216
|
+
AUTH_STORE.set("anthropicApiKey", key);
|
|
8217
|
+
console.log(colors.success(" \u2713 API key saved."));
|
|
8218
|
+
}
|
|
8219
|
+
}
|
|
8220
|
+
const auth2 = {
|
|
8221
|
+
accessToken: `apikey_${Date.now()}`,
|
|
8222
|
+
refreshToken: "",
|
|
8223
|
+
user: {
|
|
8224
|
+
id: "apikey_user",
|
|
8225
|
+
email: "apikey@local",
|
|
8226
|
+
name: "API Key User"
|
|
8227
|
+
},
|
|
8228
|
+
license: {
|
|
8229
|
+
tier: "free",
|
|
8230
|
+
// Free tier features only
|
|
8231
|
+
features: ["basic_build", "memory", "patterns"],
|
|
8232
|
+
expiresAt: null,
|
|
8233
|
+
usage: { current: 0, limit: 50 }
|
|
8234
|
+
},
|
|
8235
|
+
expiresAt: Date.now() + 30 * 24 * 60 * 60 * 1e3,
|
|
8236
|
+
// 30 days
|
|
8237
|
+
authType: "apikey"
|
|
8238
|
+
};
|
|
8239
|
+
this.saveAuth(auth2);
|
|
8240
|
+
console.log("");
|
|
8241
|
+
console.log(colors.success(" \u2713 Using API key only mode."));
|
|
8242
|
+
console.log(colors.muted(" Free tier features enabled."));
|
|
8243
|
+
console.log(colors.muted(' Run "cb login" anytime to upgrade.'));
|
|
8244
|
+
console.log("");
|
|
8245
|
+
return true;
|
|
8246
|
+
}
|
|
8247
|
+
// ============================================================================
|
|
8248
|
+
// LOGIN WITH BROWSER (Original device flow)
|
|
8249
|
+
// ============================================================================
|
|
8250
|
+
async loginWithBrowser() {
|
|
8074
8251
|
try {
|
|
8075
8252
|
const deviceCode = await this.requestDeviceCode();
|
|
8076
8253
|
if (!deviceCode) {
|
|
@@ -8099,6 +8276,15 @@ var Auth = class _Auth {
|
|
|
8099
8276
|
console.log(colors.error(" Authentication failed or timed out."));
|
|
8100
8277
|
return false;
|
|
8101
8278
|
}
|
|
8279
|
+
if (WHITELISTED_EMAILS.includes(auth2.user.email)) {
|
|
8280
|
+
auth2.license = {
|
|
8281
|
+
tier: "admin",
|
|
8282
|
+
features: ALL_FEATURES,
|
|
8283
|
+
expiresAt: null,
|
|
8284
|
+
usage: { current: 0, limit: 999999 }
|
|
8285
|
+
};
|
|
8286
|
+
auth2.authType = "whitelist";
|
|
8287
|
+
}
|
|
8102
8288
|
this.saveAuth(auth2);
|
|
8103
8289
|
console.log("");
|
|
8104
8290
|
console.log(colors.success(` \u2713 Logged in as ${auth2.user.email}`));
|
|
@@ -8121,6 +8307,13 @@ var Auth = class _Auth {
|
|
|
8121
8307
|
console.log(colors.success(" \u2713 Logged out successfully"));
|
|
8122
8308
|
}
|
|
8123
8309
|
// ============================================================================
|
|
8310
|
+
// IS LOGGED IN - Quick check
|
|
8311
|
+
// ============================================================================
|
|
8312
|
+
isLoggedIn() {
|
|
8313
|
+
const auth2 = this.getAuth();
|
|
8314
|
+
return auth2 !== null && !this.isExpired(auth2);
|
|
8315
|
+
}
|
|
8316
|
+
// ============================================================================
|
|
8124
8317
|
// WHO AM I
|
|
8125
8318
|
// ============================================================================
|
|
8126
8319
|
async whoami() {
|
|
@@ -8132,16 +8325,26 @@ var Auth = class _Auth {
|
|
|
8132
8325
|
console.log("");
|
|
8133
8326
|
return;
|
|
8134
8327
|
}
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8328
|
+
if (auth2.authType === "device") {
|
|
8329
|
+
const freshLicense = await this.verifyLicense();
|
|
8330
|
+
if (freshLicense) {
|
|
8331
|
+
auth2.license = freshLicense;
|
|
8332
|
+
this.saveAuth(auth2);
|
|
8333
|
+
}
|
|
8139
8334
|
}
|
|
8140
8335
|
console.log("");
|
|
8141
8336
|
console.log(colors.white(" \u{1F464} CodeBakers Account"));
|
|
8142
8337
|
console.log("");
|
|
8143
8338
|
console.log(colors.secondary(` Email: ${auth2.user.email}`));
|
|
8144
8339
|
console.log(colors.secondary(` Name: ${auth2.user.name}`));
|
|
8340
|
+
const authTypeLabels = {
|
|
8341
|
+
admin: "\u{1F511} Admin Access",
|
|
8342
|
+
beta: "\u{1F9EA} Beta Tester",
|
|
8343
|
+
apikey: "\u{1F527} API Key Only",
|
|
8344
|
+
whitelist: "\u2B50 Whitelisted",
|
|
8345
|
+
device: "\u{1F310} Standard"
|
|
8346
|
+
};
|
|
8347
|
+
console.log(colors.secondary(` Type: ${authTypeLabels[auth2.authType || "device"] || "Standard"}`));
|
|
8145
8348
|
console.log("");
|
|
8146
8349
|
console.log(colors.white(" \u{1F4C4} License"));
|
|
8147
8350
|
console.log(colors.secondary(` Tier: ${auth2.license.tier.toUpperCase()}`));
|
|
@@ -8157,7 +8360,7 @@ var Auth = class _Auth {
|
|
|
8157
8360
|
for (const feature of auth2.license.features) {
|
|
8158
8361
|
console.log(colors.success(` \u2713 ${this.formatFeatureName(feature)}`));
|
|
8159
8362
|
}
|
|
8160
|
-
if (auth2.license.usage) {
|
|
8363
|
+
if (auth2.license.usage && auth2.authType !== "admin") {
|
|
8161
8364
|
console.log("");
|
|
8162
8365
|
console.log(colors.white(" \u{1F4CA} Usage This Month"));
|
|
8163
8366
|
const pct = Math.round(auth2.license.usage.current / auth2.license.usage.limit * 100);
|
|
@@ -8660,7 +8863,7 @@ ${issues.map((i) => ` \u2022 ${i}`).join("\n")}` : "\n\nEverything looks good!"
|
|
|
8660
8863
|
/^(ugh|argh|damn|shit|fuck)/i
|
|
8661
8864
|
// Frustration words
|
|
8662
8865
|
];
|
|
8663
|
-
return frustrationPatterns.some((
|
|
8866
|
+
return frustrationPatterns.some((p9) => p9.test(input));
|
|
8664
8867
|
}
|
|
8665
8868
|
// ============================================================================
|
|
8666
8869
|
// RATE LIMITING (Don't be annoying)
|
|
@@ -8922,8 +9125,8 @@ ${chunk.content.slice(0, 2e3)}`
|
|
|
8922
9125
|
chunk.embedding = this.simpleEmbed(chunk.content + " " + chunk.summary);
|
|
8923
9126
|
}
|
|
8924
9127
|
}
|
|
8925
|
-
simpleEmbed(
|
|
8926
|
-
const words =
|
|
9128
|
+
simpleEmbed(text6) {
|
|
9129
|
+
const words = text6.toLowerCase().split(/\W+/).filter((w) => w.length > 2);
|
|
8927
9130
|
const embedding = new Array(256).fill(0);
|
|
8928
9131
|
for (const word of words) {
|
|
8929
9132
|
const hash = this.hashString(word);
|
|
@@ -9268,8 +9471,8 @@ ${content.slice(0, 3e3)}`
|
|
|
9268
9471
|
for (const feature of commonFeatures) {
|
|
9269
9472
|
if (!features.has(feature)) {
|
|
9270
9473
|
const relatedFiles = [...files.entries()].filter(
|
|
9271
|
-
([
|
|
9272
|
-
).map(([
|
|
9474
|
+
([path19, summary]) => path19.toLowerCase().includes(feature) || summary.summary.toLowerCase().includes(feature)
|
|
9475
|
+
).map(([path19]) => path19);
|
|
9273
9476
|
if (relatedFiles.length > 0) {
|
|
9274
9477
|
features.set(feature, {
|
|
9275
9478
|
name: feature,
|
|
@@ -9384,7 +9587,7 @@ ${featureList}`
|
|
|
9384
9587
|
"Redux": ["@reduxjs/toolkit", "redux"]
|
|
9385
9588
|
};
|
|
9386
9589
|
for (const [name, packages] of Object.entries(categories)) {
|
|
9387
|
-
if (packages.some((
|
|
9590
|
+
if (packages.some((p9) => deps.has(p9))) {
|
|
9388
9591
|
stack.push(name);
|
|
9389
9592
|
}
|
|
9390
9593
|
}
|
|
@@ -9430,8 +9633,8 @@ ${featureList}`
|
|
|
9430
9633
|
}
|
|
9431
9634
|
}
|
|
9432
9635
|
const relevantFiles = [...this.index.files.entries()].filter(
|
|
9433
|
-
([
|
|
9434
|
-
(word) => word.length > 2 && (
|
|
9636
|
+
([path19, summary]) => queryLower.split(" ").some(
|
|
9637
|
+
(word) => word.length > 2 && (path19.toLowerCase().includes(word) || summary.summary.toLowerCase().includes(word))
|
|
9435
9638
|
)
|
|
9436
9639
|
).slice(0, 10);
|
|
9437
9640
|
if (relevantFiles.length > 0) {
|
|
@@ -9516,10 +9719,411 @@ ${featureList}`
|
|
|
9516
9719
|
}
|
|
9517
9720
|
};
|
|
9518
9721
|
|
|
9519
|
-
// src/
|
|
9520
|
-
import
|
|
9722
|
+
// src/core/onboarding.ts
|
|
9723
|
+
import * as p6 from "@clack/prompts";
|
|
9521
9724
|
import fs16 from "fs-extra";
|
|
9522
9725
|
import path16 from "path";
|
|
9726
|
+
function showWelcomeScreen() {
|
|
9727
|
+
console.clear();
|
|
9728
|
+
console.log("");
|
|
9729
|
+
console.log(colors.primary(" \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\u2500\u2500\u2500\u2500\u2510"));
|
|
9730
|
+
console.log(colors.primary(" \u2502 \u2502"));
|
|
9731
|
+
console.log(colors.primary(" \u2502") + colors.white(" Welcome to CodeBakers! ") + colors.primary("\u2502"));
|
|
9732
|
+
console.log(colors.primary(" \u2502") + colors.muted(" AI Dev Team That Follows The Rules ") + colors.primary("\u2502"));
|
|
9733
|
+
console.log(colors.primary(" \u2502 \u2502"));
|
|
9734
|
+
console.log(colors.primary(" \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\u2500\u2500\u2500\u2500\u2518"));
|
|
9735
|
+
console.log("");
|
|
9736
|
+
console.log(colors.white(" Let's get you set up in 2 quick steps:"));
|
|
9737
|
+
console.log("");
|
|
9738
|
+
console.log(colors.muted(" 1. Connect your account (or use API key)"));
|
|
9739
|
+
console.log(colors.muted(" 2. Initialize your project"));
|
|
9740
|
+
console.log("");
|
|
9741
|
+
console.log(colors.dim(" Press ESC at any time to go back"));
|
|
9742
|
+
console.log("");
|
|
9743
|
+
}
|
|
9744
|
+
async function showAuthScreen() {
|
|
9745
|
+
console.clear();
|
|
9746
|
+
console.log("");
|
|
9747
|
+
console.log(colors.white(" \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\u2500\u2500\u2500\u2500\u2510"));
|
|
9748
|
+
console.log(colors.white(" \u2502") + colors.primary(" Step 1 of 2: ") + colors.white("Connect Your Account ") + colors.white("\u2502"));
|
|
9749
|
+
console.log(colors.white(" \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\u2500\u2500\u2500\u2500\u2518"));
|
|
9750
|
+
console.log("");
|
|
9751
|
+
const choice = await p6.select({
|
|
9752
|
+
message: "How would you like to connect?",
|
|
9753
|
+
options: [
|
|
9754
|
+
{
|
|
9755
|
+
value: "browser",
|
|
9756
|
+
label: "\u{1F310} Login with browser",
|
|
9757
|
+
hint: "Google or GitHub - recommended"
|
|
9758
|
+
},
|
|
9759
|
+
{
|
|
9760
|
+
value: "code",
|
|
9761
|
+
label: "\u{1F511} Enter admin/beta code",
|
|
9762
|
+
hint: "If you have a special code"
|
|
9763
|
+
},
|
|
9764
|
+
{
|
|
9765
|
+
value: "apikey",
|
|
9766
|
+
label: "\u{1F527} Use my own API key",
|
|
9767
|
+
hint: "No account needed, limited features"
|
|
9768
|
+
},
|
|
9769
|
+
{
|
|
9770
|
+
value: "skip",
|
|
9771
|
+
label: "\u23ED\uFE0F Skip for now",
|
|
9772
|
+
hint: "You can login later with /login"
|
|
9773
|
+
}
|
|
9774
|
+
]
|
|
9775
|
+
});
|
|
9776
|
+
if (p6.isCancel(choice)) {
|
|
9777
|
+
return "back";
|
|
9778
|
+
}
|
|
9779
|
+
return choice;
|
|
9780
|
+
}
|
|
9781
|
+
async function showApiKeyScreen(config) {
|
|
9782
|
+
console.clear();
|
|
9783
|
+
console.log("");
|
|
9784
|
+
console.log(colors.white(" \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\u2500\u2500\u2500\u2500\u2510"));
|
|
9785
|
+
console.log(colors.white(" \u2502") + colors.primary(" Step 1 of 2: ") + colors.white("Enter Your API Key ") + colors.white("\u2502"));
|
|
9786
|
+
console.log(colors.white(" \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\u2500\u2500\u2500\u2500\u2518"));
|
|
9787
|
+
console.log("");
|
|
9788
|
+
console.log(colors.muted(" Get your API key from: https://console.anthropic.com/"));
|
|
9789
|
+
console.log("");
|
|
9790
|
+
const apiKey = await p6.text({
|
|
9791
|
+
message: "Anthropic API Key:",
|
|
9792
|
+
placeholder: "sk-ant-api...",
|
|
9793
|
+
validate: (value) => {
|
|
9794
|
+
if (!value) return "API key is required";
|
|
9795
|
+
if (!value.startsWith("sk-ant-")) return "API key should start with sk-ant-";
|
|
9796
|
+
return void 0;
|
|
9797
|
+
}
|
|
9798
|
+
});
|
|
9799
|
+
if (p6.isCancel(apiKey)) {
|
|
9800
|
+
return "back";
|
|
9801
|
+
}
|
|
9802
|
+
config.setAnthropicKey(apiKey);
|
|
9803
|
+
console.log("");
|
|
9804
|
+
console.log(colors.success(" \u2713 API key saved"));
|
|
9805
|
+
await sleep(500);
|
|
9806
|
+
return "done";
|
|
9807
|
+
}
|
|
9808
|
+
async function showProjectScreen(memory) {
|
|
9809
|
+
console.clear();
|
|
9810
|
+
console.log("");
|
|
9811
|
+
console.log(colors.white(" \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\u2500\u2500\u2500\u2500\u2510"));
|
|
9812
|
+
console.log(colors.white(" \u2502") + colors.primary(" Step 2 of 2: ") + colors.white("Initialize Your Project ") + colors.white("\u2502"));
|
|
9813
|
+
console.log(colors.white(" \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\u2500\u2500\u2500\u2500\u2518"));
|
|
9814
|
+
console.log("");
|
|
9815
|
+
const cwd = process.cwd();
|
|
9816
|
+
const dirName = path16.basename(cwd);
|
|
9817
|
+
const hasPackageJson = await fs16.pathExists(path16.join(cwd, "package.json"));
|
|
9818
|
+
if (hasPackageJson) {
|
|
9819
|
+
console.log(colors.muted(` \u{1F4C1} Detected project: ${dirName}`));
|
|
9820
|
+
console.log("");
|
|
9821
|
+
} else {
|
|
9822
|
+
console.log(colors.muted(` \u{1F4C1} Current folder: ${dirName}`));
|
|
9823
|
+
console.log("");
|
|
9824
|
+
}
|
|
9825
|
+
const action = await p6.select({
|
|
9826
|
+
message: "What would you like to do?",
|
|
9827
|
+
options: [
|
|
9828
|
+
{
|
|
9829
|
+
value: "init",
|
|
9830
|
+
label: "\u2728 Initialize this folder as a CB project",
|
|
9831
|
+
hint: "CB will remember context about this project"
|
|
9832
|
+
},
|
|
9833
|
+
{
|
|
9834
|
+
value: "skip",
|
|
9835
|
+
label: "\u23ED\uFE0F Skip for now",
|
|
9836
|
+
hint: "You can initialize later with /init"
|
|
9837
|
+
}
|
|
9838
|
+
]
|
|
9839
|
+
});
|
|
9840
|
+
if (p6.isCancel(action)) {
|
|
9841
|
+
return "back";
|
|
9842
|
+
}
|
|
9843
|
+
if (action === "skip") {
|
|
9844
|
+
return "skip";
|
|
9845
|
+
}
|
|
9846
|
+
const projectName = await p6.text({
|
|
9847
|
+
message: "Project name:",
|
|
9848
|
+
initialValue: dirName,
|
|
9849
|
+
placeholder: dirName
|
|
9850
|
+
});
|
|
9851
|
+
if (p6.isCancel(projectName)) {
|
|
9852
|
+
return "back";
|
|
9853
|
+
}
|
|
9854
|
+
const description = await p6.text({
|
|
9855
|
+
message: "Brief description (optional):",
|
|
9856
|
+
placeholder: "A web app that..."
|
|
9857
|
+
});
|
|
9858
|
+
if (p6.isCancel(description)) {
|
|
9859
|
+
return "back";
|
|
9860
|
+
}
|
|
9861
|
+
await memory.init();
|
|
9862
|
+
memory.setIdentity(projectName, description || "");
|
|
9863
|
+
console.log("");
|
|
9864
|
+
console.log(colors.success(` \u2713 Project "${projectName}" initialized`));
|
|
9865
|
+
console.log(colors.muted(" CB will now remember context about this project"));
|
|
9866
|
+
await sleep(500);
|
|
9867
|
+
return "done";
|
|
9868
|
+
}
|
|
9869
|
+
function showCompleteScreen() {
|
|
9870
|
+
console.clear();
|
|
9871
|
+
console.log("");
|
|
9872
|
+
console.log(colors.primary(" \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\u2500\u2500\u2500\u2500\u2510"));
|
|
9873
|
+
console.log(colors.primary(" \u2502") + colors.white(" ") + colors.primary("\u2502"));
|
|
9874
|
+
console.log(colors.primary(" \u2502") + colors.success(" \u2713 You're all set! ") + colors.primary("\u2502"));
|
|
9875
|
+
console.log(colors.primary(" \u2502") + colors.white(" ") + colors.primary("\u2502"));
|
|
9876
|
+
console.log(colors.primary(" \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\u2500\u2500\u2500\u2500\u2518"));
|
|
9877
|
+
console.log("");
|
|
9878
|
+
console.log(colors.white(" Quick start:"));
|
|
9879
|
+
console.log("");
|
|
9880
|
+
console.log(colors.muted(" Just type what you want:"));
|
|
9881
|
+
console.log(colors.white(' "Add a login page"'));
|
|
9882
|
+
console.log(colors.white(' "Fix the bug in navbar"'));
|
|
9883
|
+
console.log(colors.white(' "Create an API for users"'));
|
|
9884
|
+
console.log("");
|
|
9885
|
+
console.log(colors.muted(" Or use commands:"));
|
|
9886
|
+
console.log(colors.dim(" /help ") + colors.muted("Show all commands"));
|
|
9887
|
+
console.log(colors.dim(" /audit ") + colors.muted("Check code quality"));
|
|
9888
|
+
console.log(colors.dim(" /spec ") + colors.muted("Generate a product spec"));
|
|
9889
|
+
console.log("");
|
|
9890
|
+
}
|
|
9891
|
+
async function runOnboarding(config, memory) {
|
|
9892
|
+
let currentStep = "welcome";
|
|
9893
|
+
const hasApiKey = config.isConfigured();
|
|
9894
|
+
const hasAuth = auth.isLoggedIn();
|
|
9895
|
+
const hasProject = memory.getIdentity().name !== "";
|
|
9896
|
+
if (hasAuth || hasApiKey) {
|
|
9897
|
+
if (hasProject) {
|
|
9898
|
+
return true;
|
|
9899
|
+
}
|
|
9900
|
+
currentStep = "project";
|
|
9901
|
+
}
|
|
9902
|
+
while (true) {
|
|
9903
|
+
switch (currentStep) {
|
|
9904
|
+
case "welcome": {
|
|
9905
|
+
showWelcomeScreen();
|
|
9906
|
+
const proceed = await p6.confirm({
|
|
9907
|
+
message: "Ready to begin?",
|
|
9908
|
+
initialValue: true
|
|
9909
|
+
});
|
|
9910
|
+
if (p6.isCancel(proceed) || !proceed) {
|
|
9911
|
+
return false;
|
|
9912
|
+
}
|
|
9913
|
+
currentStep = "auth";
|
|
9914
|
+
break;
|
|
9915
|
+
}
|
|
9916
|
+
case "auth": {
|
|
9917
|
+
const authChoice = await showAuthScreen();
|
|
9918
|
+
if (authChoice === "back") {
|
|
9919
|
+
currentStep = "welcome";
|
|
9920
|
+
break;
|
|
9921
|
+
}
|
|
9922
|
+
if (authChoice === "skip") {
|
|
9923
|
+
if (!config.isConfigured()) {
|
|
9924
|
+
console.log("");
|
|
9925
|
+
console.log(colors.warning(" \u26A0 You need either an account or API key to use CB"));
|
|
9926
|
+
console.log("");
|
|
9927
|
+
await sleep(1500);
|
|
9928
|
+
break;
|
|
9929
|
+
}
|
|
9930
|
+
currentStep = "project";
|
|
9931
|
+
break;
|
|
9932
|
+
}
|
|
9933
|
+
if (authChoice === "apikey") {
|
|
9934
|
+
currentStep = "api_key";
|
|
9935
|
+
break;
|
|
9936
|
+
}
|
|
9937
|
+
if (authChoice === "browser" || authChoice === "code") {
|
|
9938
|
+
const success = authChoice === "browser" ? await auth.loginWithBrowser() : await auth.loginWithCode();
|
|
9939
|
+
if (success) {
|
|
9940
|
+
currentStep = "project";
|
|
9941
|
+
}
|
|
9942
|
+
break;
|
|
9943
|
+
}
|
|
9944
|
+
break;
|
|
9945
|
+
}
|
|
9946
|
+
case "api_key": {
|
|
9947
|
+
const result = await showApiKeyScreen(config);
|
|
9948
|
+
if (result === "back") {
|
|
9949
|
+
currentStep = "auth";
|
|
9950
|
+
break;
|
|
9951
|
+
}
|
|
9952
|
+
currentStep = "project";
|
|
9953
|
+
break;
|
|
9954
|
+
}
|
|
9955
|
+
case "project": {
|
|
9956
|
+
const result = await showProjectScreen(memory);
|
|
9957
|
+
if (result === "back") {
|
|
9958
|
+
if (!config.isConfigured() && !auth.isLoggedIn()) {
|
|
9959
|
+
currentStep = "auth";
|
|
9960
|
+
}
|
|
9961
|
+
break;
|
|
9962
|
+
}
|
|
9963
|
+
currentStep = "complete";
|
|
9964
|
+
break;
|
|
9965
|
+
}
|
|
9966
|
+
case "complete": {
|
|
9967
|
+
showCompleteScreen();
|
|
9968
|
+
const ready = await p6.confirm({
|
|
9969
|
+
message: "Start using CodeBakers?",
|
|
9970
|
+
initialValue: true
|
|
9971
|
+
});
|
|
9972
|
+
if (p6.isCancel(ready)) {
|
|
9973
|
+
currentStep = "project";
|
|
9974
|
+
break;
|
|
9975
|
+
}
|
|
9976
|
+
return true;
|
|
9977
|
+
}
|
|
9978
|
+
}
|
|
9979
|
+
}
|
|
9980
|
+
}
|
|
9981
|
+
function needsOnboarding(config, memory) {
|
|
9982
|
+
const hasApiKey = config.isConfigured();
|
|
9983
|
+
const hasAuth = auth.isLoggedIn();
|
|
9984
|
+
return !hasApiKey && !hasAuth;
|
|
9985
|
+
}
|
|
9986
|
+
function sleep(ms) {
|
|
9987
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
9988
|
+
}
|
|
9989
|
+
|
|
9990
|
+
// src/utils/folder-picker.ts
|
|
9991
|
+
import { execSync } from "child_process";
|
|
9992
|
+
import path17 from "path";
|
|
9993
|
+
import os2 from "os";
|
|
9994
|
+
import * as p7 from "@clack/prompts";
|
|
9995
|
+
async function pickFolder(message = "Select a folder") {
|
|
9996
|
+
const platform = os2.platform();
|
|
9997
|
+
try {
|
|
9998
|
+
const folder = await openNativePicker(platform, message);
|
|
9999
|
+
if (folder) {
|
|
10000
|
+
return folder;
|
|
10001
|
+
}
|
|
10002
|
+
} catch (e) {
|
|
10003
|
+
}
|
|
10004
|
+
return manualFolderEntry(message);
|
|
10005
|
+
}
|
|
10006
|
+
async function openNativePicker(platform, title) {
|
|
10007
|
+
return new Promise((resolve) => {
|
|
10008
|
+
let command;
|
|
10009
|
+
let args;
|
|
10010
|
+
if (platform === "win32") {
|
|
10011
|
+
const psScript = `
|
|
10012
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
10013
|
+
$dialog = New-Object System.Windows.Forms.FolderBrowserDialog
|
|
10014
|
+
$dialog.Description = "${title}"
|
|
10015
|
+
$dialog.ShowNewFolderButton = $true
|
|
10016
|
+
if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
|
|
10017
|
+
Write-Output $dialog.SelectedPath
|
|
10018
|
+
}
|
|
10019
|
+
`;
|
|
10020
|
+
try {
|
|
10021
|
+
const result = execSync(`powershell -Command "${psScript.replace(/\n/g, " ")}"`, {
|
|
10022
|
+
encoding: "utf-8",
|
|
10023
|
+
timeout: 6e4,
|
|
10024
|
+
// 60 second timeout
|
|
10025
|
+
windowsHide: true
|
|
10026
|
+
});
|
|
10027
|
+
const folder = result.trim();
|
|
10028
|
+
resolve(folder || null);
|
|
10029
|
+
} catch {
|
|
10030
|
+
resolve(null);
|
|
10031
|
+
}
|
|
10032
|
+
return;
|
|
10033
|
+
}
|
|
10034
|
+
if (platform === "darwin") {
|
|
10035
|
+
const script = `
|
|
10036
|
+
tell application "System Events"
|
|
10037
|
+
activate
|
|
10038
|
+
set theFolder to choose folder with prompt "${title}"
|
|
10039
|
+
return POSIX path of theFolder
|
|
10040
|
+
end tell
|
|
10041
|
+
`;
|
|
10042
|
+
try {
|
|
10043
|
+
const result = execSync(`osascript -e '${script.replace(/'/g, `'"'"'`)}'`, {
|
|
10044
|
+
encoding: "utf-8",
|
|
10045
|
+
timeout: 6e4
|
|
10046
|
+
});
|
|
10047
|
+
const folder = result.trim();
|
|
10048
|
+
resolve(folder || null);
|
|
10049
|
+
} catch {
|
|
10050
|
+
resolve(null);
|
|
10051
|
+
}
|
|
10052
|
+
return;
|
|
10053
|
+
}
|
|
10054
|
+
if (platform === "linux") {
|
|
10055
|
+
try {
|
|
10056
|
+
const result = execSync(`zenity --file-selection --directory --title="${title}" 2>/dev/null`, {
|
|
10057
|
+
encoding: "utf-8",
|
|
10058
|
+
timeout: 6e4
|
|
10059
|
+
});
|
|
10060
|
+
resolve(result.trim() || null);
|
|
10061
|
+
return;
|
|
10062
|
+
} catch {
|
|
10063
|
+
try {
|
|
10064
|
+
const result = execSync(`kdialog --getexistingdirectory ~ --title "${title}" 2>/dev/null`, {
|
|
10065
|
+
encoding: "utf-8",
|
|
10066
|
+
timeout: 6e4
|
|
10067
|
+
});
|
|
10068
|
+
resolve(result.trim() || null);
|
|
10069
|
+
return;
|
|
10070
|
+
} catch {
|
|
10071
|
+
resolve(null);
|
|
10072
|
+
}
|
|
10073
|
+
}
|
|
10074
|
+
return;
|
|
10075
|
+
}
|
|
10076
|
+
resolve(null);
|
|
10077
|
+
});
|
|
10078
|
+
}
|
|
10079
|
+
async function manualFolderEntry(message) {
|
|
10080
|
+
console.log("");
|
|
10081
|
+
console.log(colors.muted(" \u{1F4A1} Tip: You can drag & drop a folder into the terminal"));
|
|
10082
|
+
console.log("");
|
|
10083
|
+
const homeDir = os2.homedir();
|
|
10084
|
+
const commonPaths = [
|
|
10085
|
+
{ label: "\u{1F4C1} Current folder", value: process.cwd() },
|
|
10086
|
+
{ label: "\u{1F3E0} Home", value: homeDir },
|
|
10087
|
+
{ label: "\u{1F4C2} Desktop", value: path17.join(homeDir, "Desktop") },
|
|
10088
|
+
{ label: "\u{1F4C2} Documents", value: path17.join(homeDir, "Documents") },
|
|
10089
|
+
{ label: "\u{1F4C2} Downloads", value: path17.join(homeDir, "Downloads") },
|
|
10090
|
+
{ label: "\u270F\uFE0F Type custom path", value: "__custom__" }
|
|
10091
|
+
];
|
|
10092
|
+
const choice = await p7.select({
|
|
10093
|
+
message,
|
|
10094
|
+
options: commonPaths.map((p9) => ({
|
|
10095
|
+
value: p9.value,
|
|
10096
|
+
label: p9.label,
|
|
10097
|
+
hint: p9.value !== "__custom__" ? p9.value : void 0
|
|
10098
|
+
}))
|
|
10099
|
+
});
|
|
10100
|
+
if (p7.isCancel(choice)) {
|
|
10101
|
+
return null;
|
|
10102
|
+
}
|
|
10103
|
+
if (choice === "__custom__") {
|
|
10104
|
+
const customPath = await p7.text({
|
|
10105
|
+
message: "Enter folder path:",
|
|
10106
|
+
placeholder: "/path/to/folder",
|
|
10107
|
+
validate: (value) => {
|
|
10108
|
+
if (!value) return "Path is required";
|
|
10109
|
+
return void 0;
|
|
10110
|
+
}
|
|
10111
|
+
});
|
|
10112
|
+
if (p7.isCancel(customPath)) {
|
|
10113
|
+
return null;
|
|
10114
|
+
}
|
|
10115
|
+
let cleanPath = customPath.trim();
|
|
10116
|
+
cleanPath = cleanPath.replace(/^["']|["']$/g, "");
|
|
10117
|
+
cleanPath = cleanPath.replace(/\\ /g, " ");
|
|
10118
|
+
return cleanPath;
|
|
10119
|
+
}
|
|
10120
|
+
return choice;
|
|
10121
|
+
}
|
|
10122
|
+
|
|
10123
|
+
// src/services/git.ts
|
|
10124
|
+
import simpleGit from "simple-git";
|
|
10125
|
+
import fs17 from "fs-extra";
|
|
10126
|
+
import path18 from "path";
|
|
9523
10127
|
var GitService = class {
|
|
9524
10128
|
git;
|
|
9525
10129
|
projectPath;
|
|
@@ -9528,7 +10132,7 @@ var GitService = class {
|
|
|
9528
10132
|
this.git = simpleGit(projectPath);
|
|
9529
10133
|
}
|
|
9530
10134
|
async isRepo() {
|
|
9531
|
-
return
|
|
10135
|
+
return fs17.pathExists(path18.join(this.projectPath, ".git"));
|
|
9532
10136
|
}
|
|
9533
10137
|
async init() {
|
|
9534
10138
|
await this.git.init();
|
|
@@ -9639,7 +10243,7 @@ var VercelService = class {
|
|
|
9639
10243
|
};
|
|
9640
10244
|
|
|
9641
10245
|
// src/index.ts
|
|
9642
|
-
var VERSION = "
|
|
10246
|
+
var VERSION = "3.3.0";
|
|
9643
10247
|
async function main() {
|
|
9644
10248
|
const config = new Config();
|
|
9645
10249
|
const args = process.argv.slice(2);
|
|
@@ -9655,22 +10259,36 @@ async function main() {
|
|
|
9655
10259
|
await runSetup(config);
|
|
9656
10260
|
return;
|
|
9657
10261
|
}
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
9661
|
-
await runSetup(config);
|
|
9662
|
-
if (!config.isConfigured()) {
|
|
9663
|
-
showError("Setup incomplete. Run `cb setup` to configure.");
|
|
9664
|
-
return;
|
|
9665
|
-
}
|
|
10262
|
+
if (args[0] === "login") {
|
|
10263
|
+
await auth.login();
|
|
10264
|
+
return;
|
|
9666
10265
|
}
|
|
9667
10266
|
const memory = new Memory();
|
|
9668
10267
|
await memory.init();
|
|
10268
|
+
if (needsOnboarding(config, memory)) {
|
|
10269
|
+
const completed = await runOnboarding(config, memory);
|
|
10270
|
+
if (!completed) {
|
|
10271
|
+
console.log("");
|
|
10272
|
+
console.log(colors.muted(" Run `cb` again when you're ready."));
|
|
10273
|
+
console.log("");
|
|
10274
|
+
return;
|
|
10275
|
+
}
|
|
10276
|
+
}
|
|
10277
|
+
showHeader();
|
|
10278
|
+
console.log(colors.muted(` v${VERSION}`));
|
|
10279
|
+
console.log("");
|
|
9669
10280
|
const scanner = new ProjectScanner();
|
|
9670
10281
|
const structure = await scanner.detectProject();
|
|
9671
10282
|
const editor = new FileEditor();
|
|
9672
10283
|
const git = new GitService();
|
|
9673
|
-
|
|
10284
|
+
const identity = memory.getIdentity();
|
|
10285
|
+
if (identity.name) {
|
|
10286
|
+
console.log(colors.white(` \u{1F4C1} ${identity.name}`) + colors.muted(` (${structure.framework || "Project"})`));
|
|
10287
|
+
} else {
|
|
10288
|
+
console.log(colors.white(` \u{1F4C1} ${structure.name}`) + colors.muted(` (${structure.framework || "Unknown"})`));
|
|
10289
|
+
console.log(colors.dim(" Run /init to enable project memory"));
|
|
10290
|
+
}
|
|
10291
|
+
console.log("");
|
|
9674
10292
|
let ai;
|
|
9675
10293
|
try {
|
|
9676
10294
|
ai = new AIEngine(config, memory, scanner);
|
|
@@ -9682,27 +10300,18 @@ async function main() {
|
|
|
9682
10300
|
const modeManager = getModeManager();
|
|
9683
10301
|
const suggestions = new SmartSuggestions(memory, scanner);
|
|
9684
10302
|
const proactive = new ProactiveAssistant(memory, scanner, config);
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
console.log(proactive.formatAction(startupAction));
|
|
9688
|
-
proactive.markSuggestionShown();
|
|
9689
|
-
}
|
|
9690
|
-
const identity = memory.getIdentity();
|
|
9691
|
-
if (!identity.name) {
|
|
9692
|
-
showInfo('Project not initialized. Say "initialize project" or use /init');
|
|
9693
|
-
}
|
|
9694
|
-
showWelcome();
|
|
9695
|
-
console.log(colors.muted(" Modes: " + modeManager.getStatusBar()));
|
|
10303
|
+
console.log(colors.muted(" Just tell me what you need:"));
|
|
10304
|
+
console.log(colors.dim(' "Add a login page" \u2022 "Fix the navbar" \u2022 /help'));
|
|
9696
10305
|
console.log("");
|
|
9697
10306
|
let lastAction;
|
|
9698
10307
|
let running = true;
|
|
9699
10308
|
while (running) {
|
|
9700
10309
|
const modePrompt = modeManager.getPrompt();
|
|
9701
|
-
const input = await
|
|
10310
|
+
const input = await p8.text({
|
|
9702
10311
|
message: modePrompt,
|
|
9703
10312
|
placeholder: "What would you like to build? (Shift+Tab to change mode)"
|
|
9704
10313
|
});
|
|
9705
|
-
if (
|
|
10314
|
+
if (p8.isCancel(input)) {
|
|
9706
10315
|
running = false;
|
|
9707
10316
|
showInfo("Goodbye! \u{1F44B}");
|
|
9708
10317
|
break;
|
|
@@ -9760,8 +10369,8 @@ async function main() {
|
|
|
9760
10369
|
showSuccess(`Decision recorded: ${result.params.content}`);
|
|
9761
10370
|
} else {
|
|
9762
10371
|
showInfo("What decision would you like to record?");
|
|
9763
|
-
const decision = await
|
|
9764
|
-
if (!
|
|
10372
|
+
const decision = await p8.text({ message: "Decision:" });
|
|
10373
|
+
if (!p8.isCancel(decision) && decision) {
|
|
9765
10374
|
memory.addDecision(decision);
|
|
9766
10375
|
await memory.save();
|
|
9767
10376
|
showSuccess(`Decision recorded: ${decision}`);
|
|
@@ -9775,8 +10384,8 @@ async function main() {
|
|
|
9775
10384
|
showSuccess(`Rule added: ${result.params.content}`);
|
|
9776
10385
|
} else {
|
|
9777
10386
|
showInfo("What rule would you like to add?");
|
|
9778
|
-
const rule = await
|
|
9779
|
-
if (!
|
|
10387
|
+
const rule = await p8.text({ message: "Rule:" });
|
|
10388
|
+
if (!p8.isCancel(rule) && rule) {
|
|
9780
10389
|
memory.addCustomRule(rule);
|
|
9781
10390
|
await memory.save();
|
|
9782
10391
|
showSuccess(`Rule added: ${rule}`);
|
|
@@ -9841,17 +10450,20 @@ async function main() {
|
|
|
9841
10450
|
case "index":
|
|
9842
10451
|
await handleIndex(ctx);
|
|
9843
10452
|
break;
|
|
10453
|
+
case "folder":
|
|
10454
|
+
await handleFolderChange();
|
|
10455
|
+
break;
|
|
9844
10456
|
case "generate":
|
|
9845
10457
|
default:
|
|
9846
10458
|
const inputHandler = new InputHandler(config, memory, scanner);
|
|
9847
10459
|
const detected = await inputHandler.detectAndProcess(cmd);
|
|
9848
10460
|
if (detected.type !== "text") {
|
|
9849
10461
|
console.log(inputHandler.formatDetection(detected));
|
|
9850
|
-
const proceed = await
|
|
10462
|
+
const proceed = await p8.confirm({
|
|
9851
10463
|
message: `Process this ${detected.type}?`,
|
|
9852
10464
|
initialValue: true
|
|
9853
10465
|
});
|
|
9854
|
-
if (!proceed ||
|
|
10466
|
+
if (!proceed || p8.isCancel(proceed)) break;
|
|
9855
10467
|
const enhancedCmd = inputHandler.enhancePrompt(detected, cmd);
|
|
9856
10468
|
await handleGeneration(enhancedCmd, ctx);
|
|
9857
10469
|
break;
|
|
@@ -9870,11 +10482,11 @@ async function main() {
|
|
|
9870
10482
|
console.log(colors.secondary(" \u{1F4A1} This looks like a complex request."));
|
|
9871
10483
|
console.log(colors.muted(" Parallel build could be ~3x faster."));
|
|
9872
10484
|
console.log("");
|
|
9873
|
-
const useParallel = await
|
|
10485
|
+
const useParallel = await p8.confirm({
|
|
9874
10486
|
message: "Use parallel build with 3 agents?",
|
|
9875
10487
|
initialValue: true
|
|
9876
10488
|
});
|
|
9877
|
-
if (useParallel && !
|
|
10489
|
+
if (useParallel && !p8.isCancel(useParallel)) {
|
|
9878
10490
|
await handleParallelBuild(cmd, ctx);
|
|
9879
10491
|
break;
|
|
9880
10492
|
}
|
|
@@ -9886,11 +10498,11 @@ async function main() {
|
|
|
9886
10498
|
console.log(colors.secondary(` \u{1F4A1} I recommend the "${suggestedTemplate.name}" template.`));
|
|
9887
10499
|
console.log(colors.muted(` ${suggestedTemplate.description}`));
|
|
9888
10500
|
console.log("");
|
|
9889
|
-
const useTemplate = await
|
|
10501
|
+
const useTemplate = await p8.confirm({
|
|
9890
10502
|
message: "Install this template first?",
|
|
9891
10503
|
initialValue: true
|
|
9892
10504
|
});
|
|
9893
|
-
if (useTemplate && !
|
|
10505
|
+
if (useTemplate && !p8.isCancel(useTemplate)) {
|
|
9894
10506
|
await handleInstallTemplate(suggestedTemplate.id, ctx);
|
|
9895
10507
|
showSuccess("Template installed! Now customizing...");
|
|
9896
10508
|
}
|
|
@@ -10029,7 +10641,7 @@ async function handleCreate(name, ctx) {
|
|
|
10029
10641
|
const { config } = ctx;
|
|
10030
10642
|
let projectName = name;
|
|
10031
10643
|
if (!projectName) {
|
|
10032
|
-
const nameInput = await
|
|
10644
|
+
const nameInput = await p8.text({
|
|
10033
10645
|
message: "Project name:",
|
|
10034
10646
|
placeholder: "my-awesome-app",
|
|
10035
10647
|
validate: (value) => {
|
|
@@ -10037,23 +10649,23 @@ async function handleCreate(name, ctx) {
|
|
|
10037
10649
|
if (!/^[a-z0-9-]+$/.test(value)) return "Use lowercase letters, numbers, and hyphens only";
|
|
10038
10650
|
}
|
|
10039
10651
|
});
|
|
10040
|
-
if (
|
|
10652
|
+
if (p8.isCancel(nameInput)) return;
|
|
10041
10653
|
projectName = nameInput;
|
|
10042
10654
|
}
|
|
10043
10655
|
console.log("");
|
|
10044
|
-
const github = await
|
|
10656
|
+
const github = await p8.confirm({
|
|
10045
10657
|
message: "Create GitHub repository?",
|
|
10046
10658
|
initialValue: !!config.getGithubToken()
|
|
10047
10659
|
});
|
|
10048
|
-
const supabase = await
|
|
10660
|
+
const supabase = await p8.confirm({
|
|
10049
10661
|
message: "Create Supabase project?",
|
|
10050
10662
|
initialValue: !!config.getSupabaseToken()
|
|
10051
10663
|
});
|
|
10052
|
-
const vercel = await
|
|
10664
|
+
const vercel = await p8.confirm({
|
|
10053
10665
|
message: "Deploy to Vercel?",
|
|
10054
10666
|
initialValue: !!config.getVercelToken()
|
|
10055
10667
|
});
|
|
10056
|
-
if (
|
|
10668
|
+
if (p8.isCancel(github) || p8.isCancel(supabase) || p8.isCancel(vercel)) return;
|
|
10057
10669
|
const creator = new ProjectCreator(config);
|
|
10058
10670
|
const spinner = ora3("Creating project...").start();
|
|
10059
10671
|
const result = await creator.create(
|
|
@@ -10114,14 +10726,14 @@ async function handleInstallTemplate(templateId, ctx) {
|
|
|
10114
10726
|
let id = templateId;
|
|
10115
10727
|
if (!id) {
|
|
10116
10728
|
const templates = templateManager.listTemplates();
|
|
10117
|
-
const choice = await
|
|
10729
|
+
const choice = await p8.select({
|
|
10118
10730
|
message: "Choose a template:",
|
|
10119
10731
|
options: templates.map((t) => ({
|
|
10120
10732
|
value: t.id,
|
|
10121
10733
|
label: `${t.name} - ${t.description}`
|
|
10122
10734
|
}))
|
|
10123
10735
|
});
|
|
10124
|
-
if (
|
|
10736
|
+
if (p8.isCancel(choice)) return;
|
|
10125
10737
|
id = choice;
|
|
10126
10738
|
}
|
|
10127
10739
|
const spinner = ora3(`Installing ${id}...`).start();
|
|
@@ -10197,11 +10809,11 @@ async function handleParallelBuild(request, ctx) {
|
|
|
10197
10809
|
console.log(colors.muted(` + ${change.path}`));
|
|
10198
10810
|
}
|
|
10199
10811
|
console.log("");
|
|
10200
|
-
const apply = await
|
|
10812
|
+
const apply = await p8.confirm({
|
|
10201
10813
|
message: "Apply all files?",
|
|
10202
10814
|
initialValue: true
|
|
10203
10815
|
});
|
|
10204
|
-
if (apply && !
|
|
10816
|
+
if (apply && !p8.isCancel(apply)) {
|
|
10205
10817
|
const applied = await editor.apply();
|
|
10206
10818
|
showSuccess(`Applied ${applied.length} files`);
|
|
10207
10819
|
for (const file of applied) {
|
|
@@ -10273,11 +10885,11 @@ async function handlePlanMode(request, ctx) {
|
|
|
10273
10885
|
const plan = await planExecutor.createPlan(request);
|
|
10274
10886
|
spinner.stop();
|
|
10275
10887
|
console.log(planExecutor.formatPlan(plan));
|
|
10276
|
-
const execute = await
|
|
10888
|
+
const execute = await p8.confirm({
|
|
10277
10889
|
message: "Execute this plan?",
|
|
10278
10890
|
initialValue: true
|
|
10279
10891
|
});
|
|
10280
|
-
if (execute && !
|
|
10892
|
+
if (execute && !p8.isCancel(execute)) {
|
|
10281
10893
|
await handleGeneration(request, ctx);
|
|
10282
10894
|
}
|
|
10283
10895
|
} catch (error) {
|
|
@@ -10340,11 +10952,11 @@ async function handleTestGeneration(filePath, ctx) {
|
|
|
10340
10952
|
const { config, scanner, editor } = ctx;
|
|
10341
10953
|
const testGen = new TestGenerator(config, scanner);
|
|
10342
10954
|
if (!filePath) {
|
|
10343
|
-
const file = await
|
|
10955
|
+
const file = await p8.text({
|
|
10344
10956
|
message: "File to generate tests for:",
|
|
10345
10957
|
placeholder: "src/components/Button.tsx"
|
|
10346
10958
|
});
|
|
10347
|
-
if (
|
|
10959
|
+
if (p8.isCancel(file) || !file) return;
|
|
10348
10960
|
filePath = file;
|
|
10349
10961
|
}
|
|
10350
10962
|
const spinner = ora3(`Generating tests for ${filePath}...`).start();
|
|
@@ -10361,11 +10973,11 @@ async function handleTestGeneration(filePath, ctx) {
|
|
|
10361
10973
|
console.log(colors.muted(" " + test.content.split("\n").slice(0, 10).join("\n ")));
|
|
10362
10974
|
console.log(colors.muted(" ..."));
|
|
10363
10975
|
console.log("");
|
|
10364
|
-
const save = await
|
|
10976
|
+
const save = await p8.confirm({
|
|
10365
10977
|
message: `Save to ${test.testPath}?`,
|
|
10366
10978
|
initialValue: true
|
|
10367
10979
|
});
|
|
10368
|
-
if (save && !
|
|
10980
|
+
if (save && !p8.isCancel(save)) {
|
|
10369
10981
|
await testGen.writeTest(test);
|
|
10370
10982
|
showSuccess(`Test saved to ${test.testPath}`);
|
|
10371
10983
|
}
|
|
@@ -10403,11 +11015,11 @@ async function handleLivePreview(ctx) {
|
|
|
10403
11015
|
const { scanner } = ctx;
|
|
10404
11016
|
const preview = new LivePreview(scanner);
|
|
10405
11017
|
if (preview.isRunning()) {
|
|
10406
|
-
const stop = await
|
|
11018
|
+
const stop = await p8.confirm({
|
|
10407
11019
|
message: "Preview is running. Stop it?",
|
|
10408
11020
|
initialValue: false
|
|
10409
11021
|
});
|
|
10410
|
-
if (stop && !
|
|
11022
|
+
if (stop && !p8.isCancel(stop)) {
|
|
10411
11023
|
await preview.stop();
|
|
10412
11024
|
showSuccess("Preview stopped");
|
|
10413
11025
|
} else {
|
|
@@ -10437,11 +11049,11 @@ async function handleSpecGeneration(input, ctx) {
|
|
|
10437
11049
|
const { config, memory, scanner, editor, ai } = ctx;
|
|
10438
11050
|
let description = input.replace(/^\/spec\s*/i, "").replace(/^\/prd\s*/i, "").replace(/^\/plan\s*/i, "").trim();
|
|
10439
11051
|
if (!description) {
|
|
10440
|
-
const desc = await
|
|
11052
|
+
const desc = await p8.text({
|
|
10441
11053
|
message: "What do you want to build?",
|
|
10442
11054
|
placeholder: "An Uber for dog walkers"
|
|
10443
11055
|
});
|
|
10444
|
-
if (
|
|
11056
|
+
if (p8.isCancel(desc) || !desc) return;
|
|
10445
11057
|
description = desc;
|
|
10446
11058
|
}
|
|
10447
11059
|
const specGen = new SpecGenerator(config);
|
|
@@ -10452,11 +11064,11 @@ async function handleSpecGeneration(input, ctx) {
|
|
|
10452
11064
|
return;
|
|
10453
11065
|
}
|
|
10454
11066
|
console.log(specGen.formatSpec(spec));
|
|
10455
|
-
const buildNow = await
|
|
11067
|
+
const buildNow = await p8.confirm({
|
|
10456
11068
|
message: "Build from this spec?",
|
|
10457
11069
|
initialValue: true
|
|
10458
11070
|
});
|
|
10459
|
-
if (buildNow && !
|
|
11071
|
+
if (buildNow && !p8.isCancel(buildNow)) {
|
|
10460
11072
|
const builder = new ProjectBuilder(config, memory, scanner, editor, ai);
|
|
10461
11073
|
let cancelled = false;
|
|
10462
11074
|
const checkCancelled = () => cancelled;
|
|
@@ -10598,7 +11210,7 @@ async function handleAudit(args, ctx) {
|
|
|
10598
11210
|
const fixType = args?.includes("critical") ? "critical" : args?.includes("all") ? "all" : null;
|
|
10599
11211
|
let issuesToFix = report.critical;
|
|
10600
11212
|
if (!fixType) {
|
|
10601
|
-
const choice = await
|
|
11213
|
+
const choice = await p8.select({
|
|
10602
11214
|
message: "What would you like to fix?",
|
|
10603
11215
|
options: [
|
|
10604
11216
|
{ value: "critical", label: `Critical issues only (${report.critical.length})` },
|
|
@@ -10606,7 +11218,7 @@ async function handleAudit(args, ctx) {
|
|
|
10606
11218
|
{ value: "all", label: `Everything (${report.totalIssues})` }
|
|
10607
11219
|
]
|
|
10608
11220
|
});
|
|
10609
|
-
if (
|
|
11221
|
+
if (p8.isCancel(choice)) return;
|
|
10610
11222
|
if (choice === "warnings") {
|
|
10611
11223
|
issuesToFix = [...report.critical, ...report.warnings];
|
|
10612
11224
|
} else if (choice === "all") {
|
|
@@ -10637,11 +11249,11 @@ async function handleAudit(args, ctx) {
|
|
|
10637
11249
|
const files = result.changes.map((c) => c.file);
|
|
10638
11250
|
await git.commitFiles(files, "fix: resolve codebase audit issues");
|
|
10639
11251
|
console.log("");
|
|
10640
|
-
const push = await
|
|
11252
|
+
const push = await p8.confirm({
|
|
10641
11253
|
message: "Push and create PR?",
|
|
10642
11254
|
initialValue: true
|
|
10643
11255
|
});
|
|
10644
|
-
if (push && !
|
|
11256
|
+
if (push && !p8.isCancel(push)) {
|
|
10645
11257
|
await git.push();
|
|
10646
11258
|
const pr = await git.createPR(branchName, await git.getMainBranch(), "Fix: Codebase Audit Issues");
|
|
10647
11259
|
if (pr?.url) {
|
|
@@ -10659,7 +11271,7 @@ async function handleAudit(args, ctx) {
|
|
|
10659
11271
|
spinner.stop();
|
|
10660
11272
|
const markdown = auditor.exportMarkdown(report);
|
|
10661
11273
|
const reportPath = "AUDIT_REPORT.md";
|
|
10662
|
-
await
|
|
11274
|
+
await fs18.writeFile(reportPath, markdown);
|
|
10663
11275
|
console.log(auditor.formatReport(report));
|
|
10664
11276
|
showSuccess(`Report saved to ${reportPath}`);
|
|
10665
11277
|
break;
|
|
@@ -10754,21 +11366,44 @@ async function handleIndex(ctx) {
|
|
|
10754
11366
|
showSuccess("Codebase indexed! Context retrieval is now smarter.");
|
|
10755
11367
|
console.log(colors.muted(" Re-run /index after major changes to keep it updated."));
|
|
10756
11368
|
}
|
|
11369
|
+
async function handleFolderChange() {
|
|
11370
|
+
console.log("");
|
|
11371
|
+
console.log(colors.white(" \u{1F4C1} Change Working Folder"));
|
|
11372
|
+
console.log("");
|
|
11373
|
+
const folder = await pickFolder("Select project folder");
|
|
11374
|
+
if (!folder) {
|
|
11375
|
+
console.log(colors.muted(" Cancelled"));
|
|
11376
|
+
return;
|
|
11377
|
+
}
|
|
11378
|
+
if (!await fs18.pathExists(folder)) {
|
|
11379
|
+
showError(`Folder not found: ${folder}`);
|
|
11380
|
+
return;
|
|
11381
|
+
}
|
|
11382
|
+
try {
|
|
11383
|
+
process.chdir(folder);
|
|
11384
|
+
console.log("");
|
|
11385
|
+
showSuccess(`Changed to: ${folder}`);
|
|
11386
|
+
console.log(colors.muted(" Restart CB to reload project context"));
|
|
11387
|
+
console.log("");
|
|
11388
|
+
} catch (error) {
|
|
11389
|
+
showError(`Cannot access folder: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
11390
|
+
}
|
|
11391
|
+
}
|
|
10757
11392
|
async function initProject(ctx) {
|
|
10758
11393
|
const { memory, scanner } = ctx;
|
|
10759
11394
|
const structure = await scanner.detectProject();
|
|
10760
11395
|
console.log("");
|
|
10761
|
-
const name = await
|
|
11396
|
+
const name = await p8.text({
|
|
10762
11397
|
message: "Project name:",
|
|
10763
11398
|
initialValue: structure.name
|
|
10764
11399
|
});
|
|
10765
|
-
if (
|
|
10766
|
-
const description = await
|
|
11400
|
+
if (p8.isCancel(name)) return;
|
|
11401
|
+
const description = await p8.text({
|
|
10767
11402
|
message: "Description:",
|
|
10768
11403
|
placeholder: "A brief description of your project"
|
|
10769
11404
|
});
|
|
10770
|
-
if (
|
|
10771
|
-
const stack = await
|
|
11405
|
+
if (p8.isCancel(description)) return;
|
|
11406
|
+
const stack = await p8.text({
|
|
10772
11407
|
message: "Tech stack (comma-separated):",
|
|
10773
11408
|
initialValue: [
|
|
10774
11409
|
structure.framework,
|
|
@@ -10777,7 +11412,7 @@ async function initProject(ctx) {
|
|
|
10777
11412
|
"Tailwind"
|
|
10778
11413
|
].filter(Boolean).join(", ")
|
|
10779
11414
|
});
|
|
10780
|
-
if (
|
|
11415
|
+
if (p8.isCancel(stack)) return;
|
|
10781
11416
|
memory.setIdentity(
|
|
10782
11417
|
name,
|
|
10783
11418
|
description,
|
|
@@ -10820,11 +11455,11 @@ async function undoChanges(ctx, steps) {
|
|
|
10820
11455
|
const snapshot = snapshots[targetIndex];
|
|
10821
11456
|
console.log("");
|
|
10822
11457
|
console.log(colors.white(` Rolling back to: ${snapshot.description}`));
|
|
10823
|
-
const
|
|
11458
|
+
const confirm8 = await p8.confirm({
|
|
10824
11459
|
message: "Proceed with rollback?",
|
|
10825
11460
|
initialValue: false
|
|
10826
11461
|
});
|
|
10827
|
-
if (
|
|
11462
|
+
if (confirm8 && !p8.isCancel(confirm8)) {
|
|
10828
11463
|
const restored = await memory.rollback(snapshot.id);
|
|
10829
11464
|
showSuccess(`Restored ${restored.length} file${restored.length > 1 ? "s" : ""}`);
|
|
10830
11465
|
}
|
|
@@ -10832,11 +11467,11 @@ async function undoChanges(ctx, steps) {
|
|
|
10832
11467
|
async function commitChanges(ctx, message) {
|
|
10833
11468
|
const { git, memory } = ctx;
|
|
10834
11469
|
if (!await git.isRepo()) {
|
|
10835
|
-
const init = await
|
|
11470
|
+
const init = await p8.confirm({
|
|
10836
11471
|
message: "No git repo found. Initialize one?",
|
|
10837
11472
|
initialValue: true
|
|
10838
11473
|
});
|
|
10839
|
-
if (init && !
|
|
11474
|
+
if (init && !p8.isCancel(init)) {
|
|
10840
11475
|
await git.init();
|
|
10841
11476
|
showSuccess("Git repository initialized");
|
|
10842
11477
|
} else {
|
|
@@ -10861,13 +11496,13 @@ async function deployProject(ctx) {
|
|
|
10861
11496
|
showError("Vercel CLI not installed. Run: npm i -g vercel");
|
|
10862
11497
|
return;
|
|
10863
11498
|
}
|
|
10864
|
-
const prod = await
|
|
11499
|
+
const prod = await p8.confirm({
|
|
10865
11500
|
message: "Deploy to production?",
|
|
10866
11501
|
initialValue: false
|
|
10867
11502
|
});
|
|
10868
11503
|
const spinner = ora3("Deploying...").start();
|
|
10869
11504
|
try {
|
|
10870
|
-
const result = await vercel.deploy(process.cwd(), prod && !
|
|
11505
|
+
const result = await vercel.deploy(process.cwd(), prod && !p8.isCancel(prod));
|
|
10871
11506
|
spinner.stop();
|
|
10872
11507
|
showSuccess(`Deployed: ${result.url}`);
|
|
10873
11508
|
} catch (error) {
|
|
@@ -10877,11 +11512,11 @@ async function deployProject(ctx) {
|
|
|
10877
11512
|
}
|
|
10878
11513
|
async function reviewCodebase(ctx) {
|
|
10879
11514
|
const { ai } = ctx;
|
|
10880
|
-
const includeAI = await
|
|
11515
|
+
const includeAI = await p8.confirm({
|
|
10881
11516
|
message: "Include AI deep analysis? (slower but more thorough)",
|
|
10882
11517
|
initialValue: true
|
|
10883
11518
|
});
|
|
10884
|
-
if (
|
|
11519
|
+
if (p8.isCancel(includeAI)) return;
|
|
10885
11520
|
const analyzer = new CodebaseAnalyzer(
|
|
10886
11521
|
process.cwd(),
|
|
10887
11522
|
includeAI ? ai : void 0
|
|
@@ -10895,11 +11530,11 @@ async function reviewCodebase(ctx) {
|
|
|
10895
11530
|
const formatted = analyzer.formatReport(report);
|
|
10896
11531
|
console.log(formatted);
|
|
10897
11532
|
if (report.byCategory.patterns.length > 0) {
|
|
10898
|
-
const fix = await
|
|
11533
|
+
const fix = await p8.confirm({
|
|
10899
11534
|
message: `Fix ${report.byCategory.patterns.length} pattern violations automatically?`,
|
|
10900
11535
|
initialValue: false
|
|
10901
11536
|
});
|
|
10902
|
-
if (fix && !
|
|
11537
|
+
if (fix && !p8.isCancel(fix)) {
|
|
10903
11538
|
showInfo("Use `/fix` command to auto-fix pattern violations (coming soon)");
|
|
10904
11539
|
}
|
|
10905
11540
|
}
|
|
@@ -10912,7 +11547,7 @@ async function runSetup(config) {
|
|
|
10912
11547
|
console.log("");
|
|
10913
11548
|
console.log(colors.white(" Setup CodeBakers CLI"));
|
|
10914
11549
|
divider();
|
|
10915
|
-
const apiKey = await
|
|
11550
|
+
const apiKey = await p8.text({
|
|
10916
11551
|
message: "Anthropic API key:",
|
|
10917
11552
|
placeholder: "sk-ant-...",
|
|
10918
11553
|
validate: (value) => {
|
|
@@ -10920,30 +11555,30 @@ async function runSetup(config) {
|
|
|
10920
11555
|
if (!value.startsWith("sk-ant-")) return "Invalid format";
|
|
10921
11556
|
}
|
|
10922
11557
|
});
|
|
10923
|
-
if (
|
|
11558
|
+
if (p8.isCancel(apiKey)) return;
|
|
10924
11559
|
config.setAnthropicKey(apiKey);
|
|
10925
|
-
const setupGithub = await
|
|
11560
|
+
const setupGithub = await p8.confirm({
|
|
10926
11561
|
message: "Set up GitHub token? (optional)",
|
|
10927
11562
|
initialValue: false
|
|
10928
11563
|
});
|
|
10929
|
-
if (setupGithub && !
|
|
10930
|
-
const token = await
|
|
11564
|
+
if (setupGithub && !p8.isCancel(setupGithub)) {
|
|
11565
|
+
const token = await p8.text({
|
|
10931
11566
|
message: "GitHub token:",
|
|
10932
11567
|
placeholder: "ghp_..."
|
|
10933
11568
|
});
|
|
10934
|
-
if (!
|
|
11569
|
+
if (!p8.isCancel(token) && token) {
|
|
10935
11570
|
config.setGithubToken(token);
|
|
10936
11571
|
}
|
|
10937
11572
|
}
|
|
10938
|
-
const setupVercel = await
|
|
11573
|
+
const setupVercel = await p8.confirm({
|
|
10939
11574
|
message: "Set up Vercel token? (optional)",
|
|
10940
11575
|
initialValue: false
|
|
10941
11576
|
});
|
|
10942
|
-
if (setupVercel && !
|
|
10943
|
-
const token = await
|
|
11577
|
+
if (setupVercel && !p8.isCancel(setupVercel)) {
|
|
11578
|
+
const token = await p8.text({
|
|
10944
11579
|
message: "Vercel token:"
|
|
10945
11580
|
});
|
|
10946
|
-
if (!
|
|
11581
|
+
if (!p8.isCancel(token) && token) {
|
|
10947
11582
|
config.setVercelToken(token);
|
|
10948
11583
|
}
|
|
10949
11584
|
}
|