codebakers 3.1.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.
Files changed (2) hide show
  1. package/dist/index.js +778 -156
  2. 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 p6 from "@clack/prompts";
9
+ import * as p8 from "@clack/prompts";
10
10
  import ora3 from "ora";
11
- import fs17 from "fs-extra";
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((p7) => p7.replace(/['"`]/g, "")));
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 text3 = line.replace(/^[-•\d.]\s*/, "").trim();
1503
- if (text3 && currentSection === "issues") {
1504
- issues.push(text3);
1505
- } else if (text3 && currentSection === "suggestions") {
1506
- suggestions.push(text3);
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 (p7) => {
1576
- const f = await this.loadFile(p7);
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
  );
@@ -1765,12 +1765,6 @@ function showHeader() {
1765
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"));
1766
1766
  console.log("");
1767
1767
  }
1768
- function showProjectStatus(name, framework) {
1769
- 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"));
1770
- console.log(colors.white(` \u{1F4C1} ${name}`) + colors.muted(` (${framework || "Unknown"})`));
1771
- 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"));
1772
- console.log("");
1773
- }
1774
1768
  function showSuccess(message) {
1775
1769
  console.log(` ${sym.check} ${colors.white(message)}`);
1776
1770
  }
@@ -1787,15 +1781,6 @@ function divider() {
1787
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"));
1788
1782
  }
1789
1783
  var promptSymbol = colors.primary("\u276F");
1790
- function showWelcome() {
1791
- console.log(colors.muted(" Just tell me what you need:"));
1792
- console.log(colors.muted(' "Add a login page" - Generate code'));
1793
- console.log(colors.muted(' "Review my code" - Analyze codebase'));
1794
- console.log(colors.muted(' "Deploy to production" - Ship it'));
1795
- console.log(colors.muted(' "Undo that" - Rollback'));
1796
- console.log(colors.muted(" /help - All commands"));
1797
- console.log("");
1798
- }
1799
1784
 
1800
1785
  // src/core/nlp.ts
1801
1786
  var INTENT_PATTERNS = [
@@ -2411,7 +2396,11 @@ var NLPInterpreter = class {
2411
2396
  "account": "whoami",
2412
2397
  "me": "whoami",
2413
2398
  "index": "index",
2414
- "rag": "index"
2399
+ "rag": "index",
2400
+ "folder": "folder",
2401
+ "cd": "folder",
2402
+ "chdir": "folder",
2403
+ "browse": "folder"
2415
2404
  };
2416
2405
  const intent = commandMap[lower] || "unclear";
2417
2406
  const params = {};
@@ -2514,12 +2503,12 @@ var NLPInterpreter = class {
2514
2503
  deploy: "This will deploy your code. Continue?"
2515
2504
  };
2516
2505
  console.log("");
2517
- const confirm7 = await p.confirm({
2506
+ const confirm8 = await p.confirm({
2518
2507
  message: colors.warning(messages[intent.type] || "Are you sure?"),
2519
2508
  initialValue: intent.type !== "deploy"
2520
2509
  // Default no for deploy
2521
2510
  });
2522
- return !p.isCancel(confirm7) && confirm7 === true;
2511
+ return !p.isCancel(confirm8) && confirm8 === true;
2523
2512
  }
2524
2513
  };
2525
2514
  var nlp = new NLPInterpreter();
@@ -2747,22 +2736,22 @@ Please provide ONLY the corrected file content with the path. No explanation nee
2747
2736
  // HELPERS
2748
2737
  // ============================================================================
2749
2738
  async findMissingPackages(packages) {
2750
- const fs18 = await import("fs-extra");
2751
- const path17 = await import("path");
2752
- const pkgPath = path17.join(this.scanner["projectPath"], "package.json");
2753
- if (!await fs18.pathExists(pkgPath)) return packages;
2754
- const pkg = await fs18.readJson(pkgPath);
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);
2755
2744
  const installed = {
2756
2745
  ...pkg.dependencies,
2757
2746
  ...pkg.devDependencies
2758
2747
  };
2759
- return packages.filter((p7) => !installed[p7]);
2748
+ return packages.filter((p9) => !installed[p9]);
2760
2749
  }
2761
- spin(text3) {
2750
+ spin(text6) {
2762
2751
  if (this.spinner) {
2763
- this.spinner.text = text3 + " (ESC to cancel)";
2752
+ this.spinner.text = text6 + " (ESC to cancel)";
2764
2753
  } else {
2765
- this.spinner = ora(text3 + " (ESC to cancel)").start();
2754
+ this.spinner = ora(text6 + " (ESC to cancel)").start();
2766
2755
  }
2767
2756
  }
2768
2757
  stop() {
@@ -4080,9 +4069,9 @@ Create ALL files listed above.`;
4080
4069
  const count = pathMap.get(file.path) || 0;
4081
4070
  pathMap.set(file.path, count + 1);
4082
4071
  }
4083
- for (const [path17, count] of pathMap) {
4072
+ for (const [path19, count] of pathMap) {
4084
4073
  if (count > 1) {
4085
- conflicts.push(`Multiple agents created: ${path17}`);
4074
+ conflicts.push(`Multiple agents created: ${path19}`);
4086
4075
  }
4087
4076
  }
4088
4077
  for (const file of files) {
@@ -4890,11 +4879,11 @@ var AgentExecutor = class {
4890
4879
  }
4891
4880
  return Array.from(packages);
4892
4881
  }
4893
- spin(text3) {
4882
+ spin(text6) {
4894
4883
  if (this.spinner) {
4895
- this.spinner.text = text3;
4884
+ this.spinner.text = text6;
4896
4885
  } else {
4897
- this.spinner = ora2(text3).start();
4886
+ this.spinner = ora2(text6).start();
4898
4887
  }
4899
4888
  }
4900
4889
  stop() {
@@ -5199,7 +5188,7 @@ ${chunks[i]}`,
5199
5188
  projectName: analysis.projectName,
5200
5189
  totalFeatures: analysis.features.length,
5201
5190
  completedFeatures: analysis.features.filter((f) => f.status === "complete").length,
5202
- currentPhase: analysis.phases.find((p7) => p7.status === "in_progress")?.id || analysis.phases[0]?.id || "",
5191
+ currentPhase: analysis.phases.find((p9) => p9.status === "in_progress")?.id || analysis.phases[0]?.id || "",
5203
5192
  currentFeature: analysis.features.find((f) => f.status === "in_progress")?.id || "",
5204
5193
  features: analysis.features.map((f) => ({ id: f.id, status: f.status })),
5205
5194
  startedAt: Date.now(),
@@ -6695,8 +6684,8 @@ var SmartGitManager = class {
6695
6684
  const pr = await this.createPR(phaseBranch, baseBranch);
6696
6685
  return pr;
6697
6686
  }
6698
- slugify(text3) {
6699
- return text3.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 30);
6687
+ slugify(text6) {
6688
+ return text6.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 30);
6700
6689
  }
6701
6690
  // ============================================================================
6702
6691
  // SMART COMMITS
@@ -6975,7 +6964,7 @@ var ProjectBuilder = class {
6975
6964
  totalDuration: 0
6976
6965
  };
6977
6966
  try {
6978
- const phaseNames = spec.buildPhases.map((p7) => p7.name.replace(/Phase \d+:\s*/i, ""));
6967
+ const phaseNames = spec.buildPhases.map((p9) => p9.name.replace(/Phase \d+:\s*/i, ""));
6979
6968
  const strategy = await this.git.createProjectStrategy(spec.name, phaseNames);
6980
6969
  console.log(this.git.formatStrategy(strategy));
6981
6970
  const proceed = await p4.confirm({
@@ -7682,7 +7671,7 @@ Return ONLY the fixed code, no explanations. Keep all other code exactly the sam
7682
7671
  return this.patterns;
7683
7672
  }
7684
7673
  enablePattern(id) {
7685
- const pattern = this.patterns.find((p7) => p7.id === id);
7674
+ const pattern = this.patterns.find((p9) => p9.id === id);
7686
7675
  if (pattern) {
7687
7676
  pattern.enabled = true;
7688
7677
  return true;
@@ -7690,7 +7679,7 @@ Return ONLY the fixed code, no explanations. Keep all other code exactly the sam
7690
7679
  return false;
7691
7680
  }
7692
7681
  disablePattern(id) {
7693
- const pattern = this.patterns.find((p7) => p7.id === id);
7682
+ const pattern = this.patterns.find((p9) => p9.id === id);
7694
7683
  if (pattern) {
7695
7684
  pattern.enabled = false;
7696
7685
  return true;
@@ -7749,8 +7738,8 @@ Return ONLY the fixed code, no explanations. Keep all other code exactly the sam
7749
7738
  formatPatterns() {
7750
7739
  let output = "\n";
7751
7740
  output += colors.white(" \u{1F4CB} Pattern Rules") + "\n\n";
7752
- const enabled = this.patterns.filter((p7) => p7.enabled);
7753
- const disabled = this.patterns.filter((p7) => !p7.enabled);
7741
+ const enabled = this.patterns.filter((p9) => p9.enabled);
7742
+ const disabled = this.patterns.filter((p9) => !p9.enabled);
7754
7743
  output += colors.success(" ENABLED") + "\n";
7755
7744
  for (const pattern of enabled) {
7756
7745
  const severityIcon = pattern.severity === "critical" ? "\u{1F534}" : pattern.severity === "warning" ? "\u{1F7E1}" : "\u{1F7E2}";
@@ -7775,7 +7764,7 @@ Return ONLY the fixed code, no explanations. Keep all other code exactly the sam
7775
7764
  return grouped;
7776
7765
  }
7777
7766
  getPatternName(id) {
7778
- const pattern = this.patterns.find((p7) => p7.id === id);
7767
+ const pattern = this.patterns.find((p9) => p9.id === id);
7779
7768
  return pattern?.name || id;
7780
7769
  }
7781
7770
  // ============================================================================
@@ -7981,7 +7970,7 @@ var SmartSuggestions = class {
7981
7970
  /platform\s*(that|which|for)/,
7982
7971
  /saas\s*(for|that|which)/
7983
7972
  ];
7984
- return ideaPatterns.some((p7) => p7.test(lower));
7973
+ return ideaPatterns.some((p9) => p9.test(lower));
7985
7974
  }
7986
7975
  looksLikeComplexRequest(input) {
7987
7976
  const lower = input.toLowerCase();
@@ -8011,7 +8000,7 @@ var SmartSuggestions = class {
8011
8000
  /clean\s*up/,
8012
8001
  /improve\s*(the\s*)?(code|quality)/
8013
8002
  ];
8014
- return patterns.some((p7) => p7.test(lower));
8003
+ return patterns.some((p9) => p9.test(lower));
8015
8004
  }
8016
8005
  // ============================================================================
8017
8006
  // DISPLAY
@@ -8041,6 +8030,23 @@ var AUTH_STORE = new Conf2({
8041
8030
  projectName: "codebakers",
8042
8031
  encryptionKey: "cb-secure-storage-key-2026"
8043
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
+ ];
8044
8050
  var FEATURES = {
8045
8051
  // Free features
8046
8052
  basic_build: "basic_build",
@@ -8057,6 +8063,7 @@ var FEATURES = {
8057
8063
  whitelabel: "whitelabel",
8058
8064
  priority_support: "priority_support"
8059
8065
  };
8066
+ var ALL_FEATURES = Object.values(FEATURES);
8060
8067
  var Auth = class _Auth {
8061
8068
  static instance;
8062
8069
  constructor() {
@@ -8068,7 +8075,7 @@ var Auth = class _Auth {
8068
8075
  return _Auth.instance;
8069
8076
  }
8070
8077
  // ============================================================================
8071
- // LOGIN FLOW
8078
+ // LOGIN FLOW - Multiple methods
8072
8079
  // ============================================================================
8073
8080
  async login() {
8074
8081
  const existing = this.getAuth();
@@ -8084,6 +8091,163 @@ var Auth = class _Auth {
8084
8091
  console.log("");
8085
8092
  console.log(colors.white(" \u{1F510} CodeBakers Login"));
8086
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() {
8087
8251
  try {
8088
8252
  const deviceCode = await this.requestDeviceCode();
8089
8253
  if (!deviceCode) {
@@ -8112,6 +8276,15 @@ var Auth = class _Auth {
8112
8276
  console.log(colors.error(" Authentication failed or timed out."));
8113
8277
  return false;
8114
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
+ }
8115
8288
  this.saveAuth(auth2);
8116
8289
  console.log("");
8117
8290
  console.log(colors.success(` \u2713 Logged in as ${auth2.user.email}`));
@@ -8134,6 +8307,13 @@ var Auth = class _Auth {
8134
8307
  console.log(colors.success(" \u2713 Logged out successfully"));
8135
8308
  }
8136
8309
  // ============================================================================
8310
+ // IS LOGGED IN - Quick check
8311
+ // ============================================================================
8312
+ isLoggedIn() {
8313
+ const auth2 = this.getAuth();
8314
+ return auth2 !== null && !this.isExpired(auth2);
8315
+ }
8316
+ // ============================================================================
8137
8317
  // WHO AM I
8138
8318
  // ============================================================================
8139
8319
  async whoami() {
@@ -8145,16 +8325,26 @@ var Auth = class _Auth {
8145
8325
  console.log("");
8146
8326
  return;
8147
8327
  }
8148
- const freshLicense = await this.verifyLicense();
8149
- if (freshLicense) {
8150
- auth2.license = freshLicense;
8151
- this.saveAuth(auth2);
8328
+ if (auth2.authType === "device") {
8329
+ const freshLicense = await this.verifyLicense();
8330
+ if (freshLicense) {
8331
+ auth2.license = freshLicense;
8332
+ this.saveAuth(auth2);
8333
+ }
8152
8334
  }
8153
8335
  console.log("");
8154
8336
  console.log(colors.white(" \u{1F464} CodeBakers Account"));
8155
8337
  console.log("");
8156
8338
  console.log(colors.secondary(` Email: ${auth2.user.email}`));
8157
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"}`));
8158
8348
  console.log("");
8159
8349
  console.log(colors.white(" \u{1F4C4} License"));
8160
8350
  console.log(colors.secondary(` Tier: ${auth2.license.tier.toUpperCase()}`));
@@ -8170,7 +8360,7 @@ var Auth = class _Auth {
8170
8360
  for (const feature of auth2.license.features) {
8171
8361
  console.log(colors.success(` \u2713 ${this.formatFeatureName(feature)}`));
8172
8362
  }
8173
- if (auth2.license.usage) {
8363
+ if (auth2.license.usage && auth2.authType !== "admin") {
8174
8364
  console.log("");
8175
8365
  console.log(colors.white(" \u{1F4CA} Usage This Month"));
8176
8366
  const pct = Math.round(auth2.license.usage.current / auth2.license.usage.limit * 100);
@@ -8673,7 +8863,7 @@ ${issues.map((i) => ` \u2022 ${i}`).join("\n")}` : "\n\nEverything looks good!"
8673
8863
  /^(ugh|argh|damn|shit|fuck)/i
8674
8864
  // Frustration words
8675
8865
  ];
8676
- return frustrationPatterns.some((p7) => p7.test(input));
8866
+ return frustrationPatterns.some((p9) => p9.test(input));
8677
8867
  }
8678
8868
  // ============================================================================
8679
8869
  // RATE LIMITING (Don't be annoying)
@@ -8935,8 +9125,8 @@ ${chunk.content.slice(0, 2e3)}`
8935
9125
  chunk.embedding = this.simpleEmbed(chunk.content + " " + chunk.summary);
8936
9126
  }
8937
9127
  }
8938
- simpleEmbed(text3) {
8939
- const words = text3.toLowerCase().split(/\W+/).filter((w) => w.length > 2);
9128
+ simpleEmbed(text6) {
9129
+ const words = text6.toLowerCase().split(/\W+/).filter((w) => w.length > 2);
8940
9130
  const embedding = new Array(256).fill(0);
8941
9131
  for (const word of words) {
8942
9132
  const hash = this.hashString(word);
@@ -9281,8 +9471,8 @@ ${content.slice(0, 3e3)}`
9281
9471
  for (const feature of commonFeatures) {
9282
9472
  if (!features.has(feature)) {
9283
9473
  const relatedFiles = [...files.entries()].filter(
9284
- ([path17, summary]) => path17.toLowerCase().includes(feature) || summary.summary.toLowerCase().includes(feature)
9285
- ).map(([path17]) => path17);
9474
+ ([path19, summary]) => path19.toLowerCase().includes(feature) || summary.summary.toLowerCase().includes(feature)
9475
+ ).map(([path19]) => path19);
9286
9476
  if (relatedFiles.length > 0) {
9287
9477
  features.set(feature, {
9288
9478
  name: feature,
@@ -9397,7 +9587,7 @@ ${featureList}`
9397
9587
  "Redux": ["@reduxjs/toolkit", "redux"]
9398
9588
  };
9399
9589
  for (const [name, packages] of Object.entries(categories)) {
9400
- if (packages.some((p7) => deps.has(p7))) {
9590
+ if (packages.some((p9) => deps.has(p9))) {
9401
9591
  stack.push(name);
9402
9592
  }
9403
9593
  }
@@ -9443,8 +9633,8 @@ ${featureList}`
9443
9633
  }
9444
9634
  }
9445
9635
  const relevantFiles = [...this.index.files.entries()].filter(
9446
- ([path17, summary]) => queryLower.split(" ").some(
9447
- (word) => word.length > 2 && (path17.toLowerCase().includes(word) || summary.summary.toLowerCase().includes(word))
9636
+ ([path19, summary]) => queryLower.split(" ").some(
9637
+ (word) => word.length > 2 && (path19.toLowerCase().includes(word) || summary.summary.toLowerCase().includes(word))
9448
9638
  )
9449
9639
  ).slice(0, 10);
9450
9640
  if (relevantFiles.length > 0) {
@@ -9529,10 +9719,411 @@ ${featureList}`
9529
9719
  }
9530
9720
  };
9531
9721
 
9532
- // src/services/git.ts
9533
- import simpleGit from "simple-git";
9722
+ // src/core/onboarding.ts
9723
+ import * as p6 from "@clack/prompts";
9534
9724
  import fs16 from "fs-extra";
9535
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";
9536
10127
  var GitService = class {
9537
10128
  git;
9538
10129
  projectPath;
@@ -9541,7 +10132,7 @@ var GitService = class {
9541
10132
  this.git = simpleGit(projectPath);
9542
10133
  }
9543
10134
  async isRepo() {
9544
- return fs16.pathExists(path16.join(this.projectPath, ".git"));
10135
+ return fs17.pathExists(path18.join(this.projectPath, ".git"));
9545
10136
  }
9546
10137
  async init() {
9547
10138
  await this.git.init();
@@ -9652,7 +10243,7 @@ var VercelService = class {
9652
10243
  };
9653
10244
 
9654
10245
  // src/index.ts
9655
- var VERSION = "1.0.0";
10246
+ var VERSION = "3.3.0";
9656
10247
  async function main() {
9657
10248
  const config = new Config();
9658
10249
  const args = process.argv.slice(2);
@@ -9668,22 +10259,36 @@ async function main() {
9668
10259
  await runSetup(config);
9669
10260
  return;
9670
10261
  }
9671
- showHeader();
9672
- if (!config.isConfigured()) {
9673
- showWarning("Not configured yet. Let's set up your API key.");
9674
- await runSetup(config);
9675
- if (!config.isConfigured()) {
9676
- showError("Setup incomplete. Run `cb setup` to configure.");
9677
- return;
9678
- }
10262
+ if (args[0] === "login") {
10263
+ await auth.login();
10264
+ return;
9679
10265
  }
9680
10266
  const memory = new Memory();
9681
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("");
9682
10280
  const scanner = new ProjectScanner();
9683
10281
  const structure = await scanner.detectProject();
9684
10282
  const editor = new FileEditor();
9685
10283
  const git = new GitService();
9686
- showProjectStatus(structure.name, structure.framework);
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("");
9687
10292
  let ai;
9688
10293
  try {
9689
10294
  ai = new AIEngine(config, memory, scanner);
@@ -9695,27 +10300,18 @@ async function main() {
9695
10300
  const modeManager = getModeManager();
9696
10301
  const suggestions = new SmartSuggestions(memory, scanner);
9697
10302
  const proactive = new ProactiveAssistant(memory, scanner, config);
9698
- const startupAction = await proactive.onStartup();
9699
- if (startupAction) {
9700
- console.log(proactive.formatAction(startupAction));
9701
- proactive.markSuggestionShown();
9702
- }
9703
- const identity = memory.getIdentity();
9704
- if (!identity.name) {
9705
- showInfo('Project not initialized. Say "initialize project" or use /init');
9706
- }
9707
- showWelcome();
9708
- 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'));
9709
10305
  console.log("");
9710
10306
  let lastAction;
9711
10307
  let running = true;
9712
10308
  while (running) {
9713
10309
  const modePrompt = modeManager.getPrompt();
9714
- const input = await p6.text({
10310
+ const input = await p8.text({
9715
10311
  message: modePrompt,
9716
10312
  placeholder: "What would you like to build? (Shift+Tab to change mode)"
9717
10313
  });
9718
- if (p6.isCancel(input)) {
10314
+ if (p8.isCancel(input)) {
9719
10315
  running = false;
9720
10316
  showInfo("Goodbye! \u{1F44B}");
9721
10317
  break;
@@ -9773,8 +10369,8 @@ async function main() {
9773
10369
  showSuccess(`Decision recorded: ${result.params.content}`);
9774
10370
  } else {
9775
10371
  showInfo("What decision would you like to record?");
9776
- const decision = await p6.text({ message: "Decision:" });
9777
- if (!p6.isCancel(decision) && decision) {
10372
+ const decision = await p8.text({ message: "Decision:" });
10373
+ if (!p8.isCancel(decision) && decision) {
9778
10374
  memory.addDecision(decision);
9779
10375
  await memory.save();
9780
10376
  showSuccess(`Decision recorded: ${decision}`);
@@ -9788,8 +10384,8 @@ async function main() {
9788
10384
  showSuccess(`Rule added: ${result.params.content}`);
9789
10385
  } else {
9790
10386
  showInfo("What rule would you like to add?");
9791
- const rule = await p6.text({ message: "Rule:" });
9792
- if (!p6.isCancel(rule) && rule) {
10387
+ const rule = await p8.text({ message: "Rule:" });
10388
+ if (!p8.isCancel(rule) && rule) {
9793
10389
  memory.addCustomRule(rule);
9794
10390
  await memory.save();
9795
10391
  showSuccess(`Rule added: ${rule}`);
@@ -9854,17 +10450,20 @@ async function main() {
9854
10450
  case "index":
9855
10451
  await handleIndex(ctx);
9856
10452
  break;
10453
+ case "folder":
10454
+ await handleFolderChange();
10455
+ break;
9857
10456
  case "generate":
9858
10457
  default:
9859
10458
  const inputHandler = new InputHandler(config, memory, scanner);
9860
10459
  const detected = await inputHandler.detectAndProcess(cmd);
9861
10460
  if (detected.type !== "text") {
9862
10461
  console.log(inputHandler.formatDetection(detected));
9863
- const proceed = await p6.confirm({
10462
+ const proceed = await p8.confirm({
9864
10463
  message: `Process this ${detected.type}?`,
9865
10464
  initialValue: true
9866
10465
  });
9867
- if (!proceed || p6.isCancel(proceed)) break;
10466
+ if (!proceed || p8.isCancel(proceed)) break;
9868
10467
  const enhancedCmd = inputHandler.enhancePrompt(detected, cmd);
9869
10468
  await handleGeneration(enhancedCmd, ctx);
9870
10469
  break;
@@ -9883,11 +10482,11 @@ async function main() {
9883
10482
  console.log(colors.secondary(" \u{1F4A1} This looks like a complex request."));
9884
10483
  console.log(colors.muted(" Parallel build could be ~3x faster."));
9885
10484
  console.log("");
9886
- const useParallel = await p6.confirm({
10485
+ const useParallel = await p8.confirm({
9887
10486
  message: "Use parallel build with 3 agents?",
9888
10487
  initialValue: true
9889
10488
  });
9890
- if (useParallel && !p6.isCancel(useParallel)) {
10489
+ if (useParallel && !p8.isCancel(useParallel)) {
9891
10490
  await handleParallelBuild(cmd, ctx);
9892
10491
  break;
9893
10492
  }
@@ -9899,11 +10498,11 @@ async function main() {
9899
10498
  console.log(colors.secondary(` \u{1F4A1} I recommend the "${suggestedTemplate.name}" template.`));
9900
10499
  console.log(colors.muted(` ${suggestedTemplate.description}`));
9901
10500
  console.log("");
9902
- const useTemplate = await p6.confirm({
10501
+ const useTemplate = await p8.confirm({
9903
10502
  message: "Install this template first?",
9904
10503
  initialValue: true
9905
10504
  });
9906
- if (useTemplate && !p6.isCancel(useTemplate)) {
10505
+ if (useTemplate && !p8.isCancel(useTemplate)) {
9907
10506
  await handleInstallTemplate(suggestedTemplate.id, ctx);
9908
10507
  showSuccess("Template installed! Now customizing...");
9909
10508
  }
@@ -10042,7 +10641,7 @@ async function handleCreate(name, ctx) {
10042
10641
  const { config } = ctx;
10043
10642
  let projectName = name;
10044
10643
  if (!projectName) {
10045
- const nameInput = await p6.text({
10644
+ const nameInput = await p8.text({
10046
10645
  message: "Project name:",
10047
10646
  placeholder: "my-awesome-app",
10048
10647
  validate: (value) => {
@@ -10050,23 +10649,23 @@ async function handleCreate(name, ctx) {
10050
10649
  if (!/^[a-z0-9-]+$/.test(value)) return "Use lowercase letters, numbers, and hyphens only";
10051
10650
  }
10052
10651
  });
10053
- if (p6.isCancel(nameInput)) return;
10652
+ if (p8.isCancel(nameInput)) return;
10054
10653
  projectName = nameInput;
10055
10654
  }
10056
10655
  console.log("");
10057
- const github = await p6.confirm({
10656
+ const github = await p8.confirm({
10058
10657
  message: "Create GitHub repository?",
10059
10658
  initialValue: !!config.getGithubToken()
10060
10659
  });
10061
- const supabase = await p6.confirm({
10660
+ const supabase = await p8.confirm({
10062
10661
  message: "Create Supabase project?",
10063
10662
  initialValue: !!config.getSupabaseToken()
10064
10663
  });
10065
- const vercel = await p6.confirm({
10664
+ const vercel = await p8.confirm({
10066
10665
  message: "Deploy to Vercel?",
10067
10666
  initialValue: !!config.getVercelToken()
10068
10667
  });
10069
- if (p6.isCancel(github) || p6.isCancel(supabase) || p6.isCancel(vercel)) return;
10668
+ if (p8.isCancel(github) || p8.isCancel(supabase) || p8.isCancel(vercel)) return;
10070
10669
  const creator = new ProjectCreator(config);
10071
10670
  const spinner = ora3("Creating project...").start();
10072
10671
  const result = await creator.create(
@@ -10127,14 +10726,14 @@ async function handleInstallTemplate(templateId, ctx) {
10127
10726
  let id = templateId;
10128
10727
  if (!id) {
10129
10728
  const templates = templateManager.listTemplates();
10130
- const choice = await p6.select({
10729
+ const choice = await p8.select({
10131
10730
  message: "Choose a template:",
10132
10731
  options: templates.map((t) => ({
10133
10732
  value: t.id,
10134
10733
  label: `${t.name} - ${t.description}`
10135
10734
  }))
10136
10735
  });
10137
- if (p6.isCancel(choice)) return;
10736
+ if (p8.isCancel(choice)) return;
10138
10737
  id = choice;
10139
10738
  }
10140
10739
  const spinner = ora3(`Installing ${id}...`).start();
@@ -10210,11 +10809,11 @@ async function handleParallelBuild(request, ctx) {
10210
10809
  console.log(colors.muted(` + ${change.path}`));
10211
10810
  }
10212
10811
  console.log("");
10213
- const apply = await p6.confirm({
10812
+ const apply = await p8.confirm({
10214
10813
  message: "Apply all files?",
10215
10814
  initialValue: true
10216
10815
  });
10217
- if (apply && !p6.isCancel(apply)) {
10816
+ if (apply && !p8.isCancel(apply)) {
10218
10817
  const applied = await editor.apply();
10219
10818
  showSuccess(`Applied ${applied.length} files`);
10220
10819
  for (const file of applied) {
@@ -10286,11 +10885,11 @@ async function handlePlanMode(request, ctx) {
10286
10885
  const plan = await planExecutor.createPlan(request);
10287
10886
  spinner.stop();
10288
10887
  console.log(planExecutor.formatPlan(plan));
10289
- const execute = await p6.confirm({
10888
+ const execute = await p8.confirm({
10290
10889
  message: "Execute this plan?",
10291
10890
  initialValue: true
10292
10891
  });
10293
- if (execute && !p6.isCancel(execute)) {
10892
+ if (execute && !p8.isCancel(execute)) {
10294
10893
  await handleGeneration(request, ctx);
10295
10894
  }
10296
10895
  } catch (error) {
@@ -10353,11 +10952,11 @@ async function handleTestGeneration(filePath, ctx) {
10353
10952
  const { config, scanner, editor } = ctx;
10354
10953
  const testGen = new TestGenerator(config, scanner);
10355
10954
  if (!filePath) {
10356
- const file = await p6.text({
10955
+ const file = await p8.text({
10357
10956
  message: "File to generate tests for:",
10358
10957
  placeholder: "src/components/Button.tsx"
10359
10958
  });
10360
- if (p6.isCancel(file) || !file) return;
10959
+ if (p8.isCancel(file) || !file) return;
10361
10960
  filePath = file;
10362
10961
  }
10363
10962
  const spinner = ora3(`Generating tests for ${filePath}...`).start();
@@ -10374,11 +10973,11 @@ async function handleTestGeneration(filePath, ctx) {
10374
10973
  console.log(colors.muted(" " + test.content.split("\n").slice(0, 10).join("\n ")));
10375
10974
  console.log(colors.muted(" ..."));
10376
10975
  console.log("");
10377
- const save = await p6.confirm({
10976
+ const save = await p8.confirm({
10378
10977
  message: `Save to ${test.testPath}?`,
10379
10978
  initialValue: true
10380
10979
  });
10381
- if (save && !p6.isCancel(save)) {
10980
+ if (save && !p8.isCancel(save)) {
10382
10981
  await testGen.writeTest(test);
10383
10982
  showSuccess(`Test saved to ${test.testPath}`);
10384
10983
  }
@@ -10416,11 +11015,11 @@ async function handleLivePreview(ctx) {
10416
11015
  const { scanner } = ctx;
10417
11016
  const preview = new LivePreview(scanner);
10418
11017
  if (preview.isRunning()) {
10419
- const stop = await p6.confirm({
11018
+ const stop = await p8.confirm({
10420
11019
  message: "Preview is running. Stop it?",
10421
11020
  initialValue: false
10422
11021
  });
10423
- if (stop && !p6.isCancel(stop)) {
11022
+ if (stop && !p8.isCancel(stop)) {
10424
11023
  await preview.stop();
10425
11024
  showSuccess("Preview stopped");
10426
11025
  } else {
@@ -10450,11 +11049,11 @@ async function handleSpecGeneration(input, ctx) {
10450
11049
  const { config, memory, scanner, editor, ai } = ctx;
10451
11050
  let description = input.replace(/^\/spec\s*/i, "").replace(/^\/prd\s*/i, "").replace(/^\/plan\s*/i, "").trim();
10452
11051
  if (!description) {
10453
- const desc = await p6.text({
11052
+ const desc = await p8.text({
10454
11053
  message: "What do you want to build?",
10455
11054
  placeholder: "An Uber for dog walkers"
10456
11055
  });
10457
- if (p6.isCancel(desc) || !desc) return;
11056
+ if (p8.isCancel(desc) || !desc) return;
10458
11057
  description = desc;
10459
11058
  }
10460
11059
  const specGen = new SpecGenerator(config);
@@ -10465,11 +11064,11 @@ async function handleSpecGeneration(input, ctx) {
10465
11064
  return;
10466
11065
  }
10467
11066
  console.log(specGen.formatSpec(spec));
10468
- const buildNow = await p6.confirm({
11067
+ const buildNow = await p8.confirm({
10469
11068
  message: "Build from this spec?",
10470
11069
  initialValue: true
10471
11070
  });
10472
- if (buildNow && !p6.isCancel(buildNow)) {
11071
+ if (buildNow && !p8.isCancel(buildNow)) {
10473
11072
  const builder = new ProjectBuilder(config, memory, scanner, editor, ai);
10474
11073
  let cancelled = false;
10475
11074
  const checkCancelled = () => cancelled;
@@ -10611,7 +11210,7 @@ async function handleAudit(args, ctx) {
10611
11210
  const fixType = args?.includes("critical") ? "critical" : args?.includes("all") ? "all" : null;
10612
11211
  let issuesToFix = report.critical;
10613
11212
  if (!fixType) {
10614
- const choice = await p6.select({
11213
+ const choice = await p8.select({
10615
11214
  message: "What would you like to fix?",
10616
11215
  options: [
10617
11216
  { value: "critical", label: `Critical issues only (${report.critical.length})` },
@@ -10619,7 +11218,7 @@ async function handleAudit(args, ctx) {
10619
11218
  { value: "all", label: `Everything (${report.totalIssues})` }
10620
11219
  ]
10621
11220
  });
10622
- if (p6.isCancel(choice)) return;
11221
+ if (p8.isCancel(choice)) return;
10623
11222
  if (choice === "warnings") {
10624
11223
  issuesToFix = [...report.critical, ...report.warnings];
10625
11224
  } else if (choice === "all") {
@@ -10650,11 +11249,11 @@ async function handleAudit(args, ctx) {
10650
11249
  const files = result.changes.map((c) => c.file);
10651
11250
  await git.commitFiles(files, "fix: resolve codebase audit issues");
10652
11251
  console.log("");
10653
- const push = await p6.confirm({
11252
+ const push = await p8.confirm({
10654
11253
  message: "Push and create PR?",
10655
11254
  initialValue: true
10656
11255
  });
10657
- if (push && !p6.isCancel(push)) {
11256
+ if (push && !p8.isCancel(push)) {
10658
11257
  await git.push();
10659
11258
  const pr = await git.createPR(branchName, await git.getMainBranch(), "Fix: Codebase Audit Issues");
10660
11259
  if (pr?.url) {
@@ -10672,7 +11271,7 @@ async function handleAudit(args, ctx) {
10672
11271
  spinner.stop();
10673
11272
  const markdown = auditor.exportMarkdown(report);
10674
11273
  const reportPath = "AUDIT_REPORT.md";
10675
- await fs17.writeFile(reportPath, markdown);
11274
+ await fs18.writeFile(reportPath, markdown);
10676
11275
  console.log(auditor.formatReport(report));
10677
11276
  showSuccess(`Report saved to ${reportPath}`);
10678
11277
  break;
@@ -10767,21 +11366,44 @@ async function handleIndex(ctx) {
10767
11366
  showSuccess("Codebase indexed! Context retrieval is now smarter.");
10768
11367
  console.log(colors.muted(" Re-run /index after major changes to keep it updated."));
10769
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
+ }
10770
11392
  async function initProject(ctx) {
10771
11393
  const { memory, scanner } = ctx;
10772
11394
  const structure = await scanner.detectProject();
10773
11395
  console.log("");
10774
- const name = await p6.text({
11396
+ const name = await p8.text({
10775
11397
  message: "Project name:",
10776
11398
  initialValue: structure.name
10777
11399
  });
10778
- if (p6.isCancel(name)) return;
10779
- const description = await p6.text({
11400
+ if (p8.isCancel(name)) return;
11401
+ const description = await p8.text({
10780
11402
  message: "Description:",
10781
11403
  placeholder: "A brief description of your project"
10782
11404
  });
10783
- if (p6.isCancel(description)) return;
10784
- const stack = await p6.text({
11405
+ if (p8.isCancel(description)) return;
11406
+ const stack = await p8.text({
10785
11407
  message: "Tech stack (comma-separated):",
10786
11408
  initialValue: [
10787
11409
  structure.framework,
@@ -10790,7 +11412,7 @@ async function initProject(ctx) {
10790
11412
  "Tailwind"
10791
11413
  ].filter(Boolean).join(", ")
10792
11414
  });
10793
- if (p6.isCancel(stack)) return;
11415
+ if (p8.isCancel(stack)) return;
10794
11416
  memory.setIdentity(
10795
11417
  name,
10796
11418
  description,
@@ -10833,11 +11455,11 @@ async function undoChanges(ctx, steps) {
10833
11455
  const snapshot = snapshots[targetIndex];
10834
11456
  console.log("");
10835
11457
  console.log(colors.white(` Rolling back to: ${snapshot.description}`));
10836
- const confirm7 = await p6.confirm({
11458
+ const confirm8 = await p8.confirm({
10837
11459
  message: "Proceed with rollback?",
10838
11460
  initialValue: false
10839
11461
  });
10840
- if (confirm7 && !p6.isCancel(confirm7)) {
11462
+ if (confirm8 && !p8.isCancel(confirm8)) {
10841
11463
  const restored = await memory.rollback(snapshot.id);
10842
11464
  showSuccess(`Restored ${restored.length} file${restored.length > 1 ? "s" : ""}`);
10843
11465
  }
@@ -10845,11 +11467,11 @@ async function undoChanges(ctx, steps) {
10845
11467
  async function commitChanges(ctx, message) {
10846
11468
  const { git, memory } = ctx;
10847
11469
  if (!await git.isRepo()) {
10848
- const init = await p6.confirm({
11470
+ const init = await p8.confirm({
10849
11471
  message: "No git repo found. Initialize one?",
10850
11472
  initialValue: true
10851
11473
  });
10852
- if (init && !p6.isCancel(init)) {
11474
+ if (init && !p8.isCancel(init)) {
10853
11475
  await git.init();
10854
11476
  showSuccess("Git repository initialized");
10855
11477
  } else {
@@ -10874,13 +11496,13 @@ async function deployProject(ctx) {
10874
11496
  showError("Vercel CLI not installed. Run: npm i -g vercel");
10875
11497
  return;
10876
11498
  }
10877
- const prod = await p6.confirm({
11499
+ const prod = await p8.confirm({
10878
11500
  message: "Deploy to production?",
10879
11501
  initialValue: false
10880
11502
  });
10881
11503
  const spinner = ora3("Deploying...").start();
10882
11504
  try {
10883
- const result = await vercel.deploy(process.cwd(), prod && !p6.isCancel(prod));
11505
+ const result = await vercel.deploy(process.cwd(), prod && !p8.isCancel(prod));
10884
11506
  spinner.stop();
10885
11507
  showSuccess(`Deployed: ${result.url}`);
10886
11508
  } catch (error) {
@@ -10890,11 +11512,11 @@ async function deployProject(ctx) {
10890
11512
  }
10891
11513
  async function reviewCodebase(ctx) {
10892
11514
  const { ai } = ctx;
10893
- const includeAI = await p6.confirm({
11515
+ const includeAI = await p8.confirm({
10894
11516
  message: "Include AI deep analysis? (slower but more thorough)",
10895
11517
  initialValue: true
10896
11518
  });
10897
- if (p6.isCancel(includeAI)) return;
11519
+ if (p8.isCancel(includeAI)) return;
10898
11520
  const analyzer = new CodebaseAnalyzer(
10899
11521
  process.cwd(),
10900
11522
  includeAI ? ai : void 0
@@ -10908,11 +11530,11 @@ async function reviewCodebase(ctx) {
10908
11530
  const formatted = analyzer.formatReport(report);
10909
11531
  console.log(formatted);
10910
11532
  if (report.byCategory.patterns.length > 0) {
10911
- const fix = await p6.confirm({
11533
+ const fix = await p8.confirm({
10912
11534
  message: `Fix ${report.byCategory.patterns.length} pattern violations automatically?`,
10913
11535
  initialValue: false
10914
11536
  });
10915
- if (fix && !p6.isCancel(fix)) {
11537
+ if (fix && !p8.isCancel(fix)) {
10916
11538
  showInfo("Use `/fix` command to auto-fix pattern violations (coming soon)");
10917
11539
  }
10918
11540
  }
@@ -10925,7 +11547,7 @@ async function runSetup(config) {
10925
11547
  console.log("");
10926
11548
  console.log(colors.white(" Setup CodeBakers CLI"));
10927
11549
  divider();
10928
- const apiKey = await p6.text({
11550
+ const apiKey = await p8.text({
10929
11551
  message: "Anthropic API key:",
10930
11552
  placeholder: "sk-ant-...",
10931
11553
  validate: (value) => {
@@ -10933,30 +11555,30 @@ async function runSetup(config) {
10933
11555
  if (!value.startsWith("sk-ant-")) return "Invalid format";
10934
11556
  }
10935
11557
  });
10936
- if (p6.isCancel(apiKey)) return;
11558
+ if (p8.isCancel(apiKey)) return;
10937
11559
  config.setAnthropicKey(apiKey);
10938
- const setupGithub = await p6.confirm({
11560
+ const setupGithub = await p8.confirm({
10939
11561
  message: "Set up GitHub token? (optional)",
10940
11562
  initialValue: false
10941
11563
  });
10942
- if (setupGithub && !p6.isCancel(setupGithub)) {
10943
- const token = await p6.text({
11564
+ if (setupGithub && !p8.isCancel(setupGithub)) {
11565
+ const token = await p8.text({
10944
11566
  message: "GitHub token:",
10945
11567
  placeholder: "ghp_..."
10946
11568
  });
10947
- if (!p6.isCancel(token) && token) {
11569
+ if (!p8.isCancel(token) && token) {
10948
11570
  config.setGithubToken(token);
10949
11571
  }
10950
11572
  }
10951
- const setupVercel = await p6.confirm({
11573
+ const setupVercel = await p8.confirm({
10952
11574
  message: "Set up Vercel token? (optional)",
10953
11575
  initialValue: false
10954
11576
  });
10955
- if (setupVercel && !p6.isCancel(setupVercel)) {
10956
- const token = await p6.text({
11577
+ if (setupVercel && !p8.isCancel(setupVercel)) {
11578
+ const token = await p8.text({
10957
11579
  message: "Vercel token:"
10958
11580
  });
10959
- if (!p6.isCancel(token) && token) {
11581
+ if (!p8.isCancel(token) && token) {
10960
11582
  config.setVercelToken(token);
10961
11583
  }
10962
11584
  }