codebakers 2.3.5 → 2.3.6

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 (3) hide show
  1. package/dist/index.js +187 -123
  2. package/package.json +1 -1
  3. package/src/index.ts +134 -73
package/dist/index.js CHANGED
@@ -2185,20 +2185,20 @@ async function getVoiceInput(prompt) {
2185
2185
  if (action === "retry") {
2186
2186
  return await getVoiceInput(prompt);
2187
2187
  } else {
2188
- const text16 = await p4.text({ message: "Type your response:" });
2189
- return p4.isCancel(text16) ? null : text16;
2188
+ const text17 = await p4.text({ message: "Type your response:" });
2189
+ return p4.isCancel(text17) ? null : text17;
2190
2190
  }
2191
2191
  }
2192
2192
  } else {
2193
2193
  console.log(chalk5.yellow("\n No speech detected. Try again or type your response.\n"));
2194
- const text16 = await p4.text({ message: "Type instead:" });
2195
- return p4.isCancel(text16) ? null : text16;
2194
+ const text17 = await p4.text({ message: "Type instead:" });
2195
+ return p4.isCancel(text17) ? null : text17;
2196
2196
  }
2197
2197
  } catch (error) {
2198
2198
  spinner16.stop("Recording failed");
2199
2199
  console.log(chalk5.yellow("Voice input failed. Please type instead."));
2200
- const text16 = await p4.text({ message: prompt });
2201
- return p4.isCancel(text16) ? null : text16;
2200
+ const text17 = await p4.text({ message: prompt });
2201
+ return p4.isCancel(text17) ? null : text17;
2202
2202
  }
2203
2203
  }
2204
2204
  async function playBeep() {
@@ -2333,10 +2333,10 @@ async function transcribeWithWhisper(audioFile) {
2333
2333
  ], { timeout: 6e4 });
2334
2334
  const txtFile = outputBase + ".txt";
2335
2335
  if (await fs4.pathExists(txtFile)) {
2336
- const text16 = await fs4.readFile(txtFile, "utf-8");
2336
+ const text17 = await fs4.readFile(txtFile, "utf-8");
2337
2337
  await fs4.remove(txtFile).catch(() => {
2338
2338
  });
2339
- return text16.trim();
2339
+ return text17.trim();
2340
2340
  }
2341
2341
  } catch {
2342
2342
  }
@@ -2443,9 +2443,9 @@ async function readFile5(filePath) {
2443
2443
  name
2444
2444
  };
2445
2445
  } else if (pdfExtensions.includes(ext)) {
2446
- const text16 = await extractPdfText(cleanPath);
2447
- if (text16) {
2448
- return { content: text16, type: "pdf", name };
2446
+ const text17 = await extractPdfText(cleanPath);
2447
+ if (text17) {
2448
+ return { content: text17, type: "pdf", name };
2449
2449
  }
2450
2450
  return {
2451
2451
  content: `[PDF file: ${name} - text extraction not available]`,
@@ -2517,19 +2517,19 @@ function formatFilesForContext(files) {
2517
2517
  context += "--- END FILES ---\n\n";
2518
2518
  return context;
2519
2519
  }
2520
- function looksLikePaste(text16) {
2521
- if (text16.includes("\n") && text16.split("\n").length > 3) return true;
2522
- if (text16.includes("function ") || text16.includes("const ") || text16.includes("import ") || text16.includes("export ") || text16.includes("class ") || text16.includes("def ") || text16.includes("public ") || text16.includes("private ")) return true;
2523
- if (text16.startsWith("{") && text16.endsWith("}") || text16.startsWith("[") && text16.endsWith("]")) return true;
2524
- if (text16.length > 200 && !text16.includes("\n")) return true;
2520
+ function looksLikePaste(text17) {
2521
+ if (text17.includes("\n") && text17.split("\n").length > 3) return true;
2522
+ if (text17.includes("function ") || text17.includes("const ") || text17.includes("import ") || text17.includes("export ") || text17.includes("class ") || text17.includes("def ") || text17.includes("public ") || text17.includes("private ")) return true;
2523
+ if (text17.startsWith("{") && text17.endsWith("}") || text17.startsWith("[") && text17.endsWith("]")) return true;
2524
+ if (text17.length > 200 && !text17.includes("\n")) return true;
2525
2525
  return false;
2526
2526
  }
2527
- async function handlePastedContent(text16) {
2528
- if (!looksLikePaste(text16)) {
2527
+ async function handlePastedContent(text17) {
2528
+ if (!looksLikePaste(text17)) {
2529
2529
  return null;
2530
2530
  }
2531
2531
  console.log(chalk6.cyan("\n\u{1F4CB} Detected pasted content!\n"));
2532
- const preview = text16.length > 200 ? text16.slice(0, 200) + "..." : text16;
2532
+ const preview = text17.length > 200 ? text17.slice(0, 200) + "..." : text17;
2533
2533
  console.log(chalk6.dim(preview));
2534
2534
  console.log("");
2535
2535
  const action = await p5.select({
@@ -2545,7 +2545,7 @@ async function handlePastedContent(text16) {
2545
2545
  });
2546
2546
  if (p5.isCancel(action)) return null;
2547
2547
  if (action === "literal") {
2548
- return { prompt: text16, context: "" };
2548
+ return { prompt: text17, context: "" };
2549
2549
  }
2550
2550
  if (action === "custom") {
2551
2551
  const instruction = await p5.text({
@@ -2559,7 +2559,7 @@ async function handlePastedContent(text16) {
2559
2559
 
2560
2560
  --- PASTED CODE ---
2561
2561
  \`\`\`
2562
- ${text16}
2562
+ ${text17}
2563
2563
  \`\`\`
2564
2564
  --- END ---
2565
2565
 
@@ -2578,7 +2578,7 @@ ${text16}
2578
2578
 
2579
2579
  --- PASTED CODE ---
2580
2580
  \`\`\`
2581
- ${text16}
2581
+ ${text17}
2582
2582
  \`\`\`
2583
2583
  --- END ---
2584
2584
 
@@ -4936,21 +4936,21 @@ async function extractMigrationSQL(tool, errorOutput) {
4936
4936
  }
4937
4937
  return null;
4938
4938
  }
4939
- async function copyToClipboard(text16) {
4939
+ async function copyToClipboard(text17) {
4940
4940
  try {
4941
4941
  const platform = process.platform;
4942
4942
  if (platform === "win32") {
4943
- const proc = await execa8("clip", { input: text16, reject: false });
4943
+ const proc = await execa8("clip", { input: text17, reject: false });
4944
4944
  return proc.exitCode === 0;
4945
4945
  } else if (platform === "darwin") {
4946
- const proc = await execa8("pbcopy", { input: text16, reject: false });
4946
+ const proc = await execa8("pbcopy", { input: text17, reject: false });
4947
4947
  return proc.exitCode === 0;
4948
4948
  } else {
4949
4949
  try {
4950
- const proc = await execa8("xclip", ["-selection", "clipboard"], { input: text16, reject: false });
4950
+ const proc = await execa8("xclip", ["-selection", "clipboard"], { input: text17, reject: false });
4951
4951
  return proc.exitCode === 0;
4952
4952
  } catch {
4953
- const proc = await execa8("xsel", ["--clipboard", "--input"], { input: text16, reject: false });
4953
+ const proc = await execa8("xsel", ["--clipboard", "--input"], { input: text17, reject: false });
4954
4954
  return proc.exitCode === 0;
4955
4955
  }
4956
4956
  }
@@ -5219,8 +5219,8 @@ async function getVoiceInput2(prompt) {
5219
5219
  initialValue: true
5220
5220
  });
5221
5221
  if (!ready || p16.isCancel(ready)) {
5222
- const text17 = await p16.text({ message: "Type instead:" });
5223
- return p16.isCancel(text17) ? null : text17;
5222
+ const text18 = await p16.text({ message: "Type instead:" });
5223
+ return p16.isCancel(text18) ? null : text18;
5224
5224
  }
5225
5225
  const spinner16 = p16.spinner();
5226
5226
  spinner16.start("\u{1F534} Recording... (press Ctrl+C to stop)");
@@ -5256,8 +5256,8 @@ async function getVoiceInput2(prompt) {
5256
5256
  if (retry === "retry") {
5257
5257
  return await getVoiceInput2(prompt);
5258
5258
  } else {
5259
- const text17 = await p16.text({ message: "Type your response:" });
5260
- return p16.isCancel(text17) ? null : text17;
5259
+ const text18 = await p16.text({ message: "Type your response:" });
5260
+ return p16.isCancel(text18) ? null : text18;
5261
5261
  }
5262
5262
  }
5263
5263
  }
@@ -5265,8 +5265,8 @@ async function getVoiceInput2(prompt) {
5265
5265
  spinner16.stop("Recording failed");
5266
5266
  console.log(chalk17.yellow("Voice input failed. Falling back to text."));
5267
5267
  }
5268
- const text16 = await p16.text({ message: prompt });
5269
- return p16.isCancel(text16) ? null : text16;
5268
+ const text17 = await p16.text({ message: prompt });
5269
+ return p16.isCancel(text17) ? null : text17;
5270
5270
  }
5271
5271
  async function recordWithWindowsSpeech2() {
5272
5272
  const psScript = `
@@ -5321,9 +5321,9 @@ async function recordWithMacOS2() {
5321
5321
  });
5322
5322
  const txtFile = tempFile.replace(".wav", ".txt");
5323
5323
  if (await fs13.pathExists(txtFile)) {
5324
- const text16 = await fs13.readFile(txtFile, "utf-8");
5324
+ const text17 = await fs13.readFile(txtFile, "utf-8");
5325
5325
  await fs13.remove(txtFile);
5326
- return text16.trim();
5326
+ return text17.trim();
5327
5327
  }
5328
5328
  } catch {
5329
5329
  }
@@ -5371,9 +5371,9 @@ async function recordWithLinux2() {
5371
5371
  });
5372
5372
  const txtFile = tempFile.replace(".wav", ".txt");
5373
5373
  if (await fs13.pathExists(txtFile)) {
5374
- const text16 = await fs13.readFile(txtFile, "utf-8");
5374
+ const text17 = await fs13.readFile(txtFile, "utf-8");
5375
5375
  await fs13.remove(txtFile);
5376
- return text16.trim();
5376
+ return text17.trim();
5377
5377
  }
5378
5378
  } catch {
5379
5379
  }
@@ -5646,8 +5646,8 @@ Think about:
5646
5646
  - What needs data from other features (dashboards, reports)?`
5647
5647
  }]
5648
5648
  });
5649
- const text16 = response.content[0].type === "text" ? response.content[0].text : "";
5650
- const jsonMatch = text16.match(/\{[\s\S]*\}/);
5649
+ const text17 = response.content[0].type === "text" ? response.content[0].text : "";
5650
+ const jsonMatch = text17.match(/\{[\s\S]*\}/);
5651
5651
  if (!jsonMatch) {
5652
5652
  throw new Error("Failed to parse PRD analysis");
5653
5653
  }
@@ -5891,9 +5891,9 @@ Start with the index.ts that exports everything.`
5891
5891
  max_tokens: 8192,
5892
5892
  messages
5893
5893
  });
5894
- const text16 = response.content[0].type === "text" ? response.content[0].text : "";
5895
- messages.push({ role: "assistant", content: text16 });
5896
- const questionMatch = text16.match(/<<<ASK_USER>>>([\s\S]*?)<<<END_ASK>>>/);
5894
+ const text17 = response.content[0].type === "text" ? response.content[0].text : "";
5895
+ messages.push({ role: "assistant", content: text17 });
5896
+ const questionMatch = text17.match(/<<<ASK_USER>>>([\s\S]*?)<<<END_ASK>>>/);
5897
5897
  if (questionMatch) {
5898
5898
  const questionBlock = questionMatch[1];
5899
5899
  const questionLine = questionBlock.match(/question:\s*(.+)/);
@@ -5922,7 +5922,7 @@ Now continue building the feature with this choice. Generate the code files.`
5922
5922
  }
5923
5923
  }
5924
5924
  if (onProgress) onProgress(60, "Writing files...");
5925
- const files = await writeFilesFromResponse(text16, projectPath);
5925
+ const files = await writeFilesFromResponse(text17, projectPath);
5926
5926
  agent.files = files;
5927
5927
  if (onProgress) onProgress(80, "Validating...");
5928
5928
  if (files.length === 0) {
@@ -6005,8 +6005,8 @@ Common fixes:
6005
6005
  - Timeout \u2192 retry with simpler approach`
6006
6006
  }]
6007
6007
  });
6008
- const text16 = response.content[0].type === "text" ? response.content[0].text : "";
6009
- const jsonMatch = text16.match(/\{[\s\S]*\}/);
6008
+ const text17 = response.content[0].type === "text" ? response.content[0].text : "";
6009
+ const jsonMatch = text17.match(/\{[\s\S]*\}/);
6010
6010
  if (!jsonMatch) {
6011
6011
  return {
6012
6012
  canFix: false,
@@ -6046,8 +6046,8 @@ content
6046
6046
  Make sure all features are accessible and properly connected.`
6047
6047
  }]
6048
6048
  });
6049
- const text16 = response.content[0].type === "text" ? response.content[0].text : "";
6050
- await writeFilesFromResponse(text16, projectPath);
6049
+ const text17 = response.content[0].type === "text" ? response.content[0].text : "";
6050
+ await writeFilesFromResponse(text17, projectPath);
6051
6051
  await execa9("git", ["add", "."], { cwd: projectPath });
6052
6052
  await execa9("git", ["commit", "-m", "Integration: wire up all features"], { cwd: projectPath, reject: false });
6053
6053
  spinner16.stop("Integration complete");
@@ -6139,11 +6139,11 @@ var ProgressDisplay = class {
6139
6139
  return chalk18.green("\u2588".repeat(filled)) + chalk18.gray("\u2591".repeat(empty));
6140
6140
  }
6141
6141
  };
6142
- async function writeFilesFromResponse(text16, projectPath) {
6142
+ async function writeFilesFromResponse(text17, projectPath) {
6143
6143
  const fileRegex = /<<<FILE:\s*(.+?)>>>([\s\S]*?)<<<END_FILE>>>/g;
6144
6144
  const files = [];
6145
6145
  let match;
6146
- while ((match = fileRegex.exec(text16)) !== null) {
6146
+ while ((match = fileRegex.exec(text17)) !== null) {
6147
6147
  const filePath = path13.join(projectPath, match[1].trim());
6148
6148
  const content = match[2].trim();
6149
6149
  await fs14.ensureDir(path13.dirname(filePath));
@@ -7179,8 +7179,8 @@ Make the content compelling and professional. Use appropriate sections for the t
7179
7179
  }]
7180
7180
  });
7181
7181
  spinner16.stop("Got it!");
7182
- const text16 = response.content[0].type === "text" ? response.content[0].text : "";
7183
- const jsonMatch = text16.match(/\{[\s\S]*\}/);
7182
+ const text17 = response.content[0].type === "text" ? response.content[0].text : "";
7183
+ const jsonMatch = text17.match(/\{[\s\S]*\}/);
7184
7184
  if (!jsonMatch) {
7185
7185
  p19.log.error("Failed to understand website description");
7186
7186
  return null;
@@ -7253,8 +7253,8 @@ Make the content specific and compelling for this business.`
7253
7253
  }]
7254
7254
  });
7255
7255
  spinner16.stop("Template customized!");
7256
- const text16 = response.content[0].type === "text" ? response.content[0].text : "";
7257
- const jsonMatch = text16.match(/\{[\s\S]*\}/);
7256
+ const text17 = response.content[0].type === "text" ? response.content[0].text : "";
7257
+ const jsonMatch = text17.match(/\{[\s\S]*\}/);
7258
7258
  if (!jsonMatch) {
7259
7259
  p19.log.error("Failed to customize template");
7260
7260
  return null;
@@ -7314,8 +7314,8 @@ Capture the FEEL of the inspiration but make it original.`
7314
7314
  }]
7315
7315
  });
7316
7316
  spinner16.stop("Design analyzed!");
7317
- const text16 = response.content[0].type === "text" ? response.content[0].text : "";
7318
- const jsonMatch = text16.match(/\{[\s\S]*\}/);
7317
+ const text17 = response.content[0].type === "text" ? response.content[0].text : "";
7318
+ const jsonMatch = text17.match(/\{[\s\S]*\}/);
7319
7319
  if (!jsonMatch) {
7320
7320
  p19.log.error("Failed to analyze design");
7321
7321
  return null;
@@ -7414,11 +7414,11 @@ content
7414
7414
  Make it production-quality and visually impressive.`
7415
7415
  }]
7416
7416
  });
7417
- const text16 = response.content[0].type === "text" ? response.content[0].text : "";
7417
+ const text17 = response.content[0].type === "text" ? response.content[0].text : "";
7418
7418
  const fileRegex = /<<<FILE:\s*(.+?)>>>([\s\S]*?)<<<END_FILE>>>/g;
7419
7419
  let match;
7420
7420
  let fileCount = 0;
7421
- while ((match = fileRegex.exec(text16)) !== null) {
7421
+ while ((match = fileRegex.exec(text17)) !== null) {
7422
7422
  const filePath = path15.join(projectPath, match[1].trim());
7423
7423
  const content = match[2].trim();
7424
7424
  await fs16.ensureDir(path15.dirname(filePath));
@@ -7618,8 +7618,8 @@ If the input is asking to build/create/add a specific feature, use "code" and pu
7618
7618
  If unclear between multiple commands, use the most likely one with lower confidence.`
7619
7619
  }]
7620
7620
  });
7621
- const text16 = response.content[0].type === "text" ? response.content[0].text : "";
7622
- const jsonMatch = text16.match(/\{[\s\S]*?\}/);
7621
+ const text17 = response.content[0].type === "text" ? response.content[0].text : "";
7622
+ const jsonMatch = text17.match(/\{[\s\S]*?\}/);
7623
7623
  if (!jsonMatch) {
7624
7624
  return {
7625
7625
  command: "code",
@@ -7632,7 +7632,7 @@ If unclear between multiple commands, use the most likely one with lower confide
7632
7632
  }
7633
7633
 
7634
7634
  // src/index.ts
7635
- var VERSION2 = "2.3.5";
7635
+ var VERSION2 = "2.3.6";
7636
7636
  var logo = `
7637
7637
  \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
7638
7638
  \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
@@ -7674,84 +7674,148 @@ async function showMainMenu() {
7674
7674
  }
7675
7675
  }
7676
7676
  async function showStartMenu(config) {
7677
- console.log(chalk21.cyan("\n \u2139\uFE0F This folder doesn't have a project yet."));
7678
- console.log(chalk21.dim(" Use the arrow keys to select an option, then press Enter.\n"));
7677
+ console.log(chalk21.cyan("\n \u2139\uFE0F This folder doesn't have a project yet.\n"));
7679
7678
  let keepRunning = true;
7680
7679
  while (keepRunning) {
7681
- const action = await p21.select({
7682
- message: "What would you like to do?",
7683
- options: [
7684
- { value: "website", label: "\u{1F310} Build a website", hint: "Describe it, AI builds it" },
7685
- { value: "new", label: "\u{1F195} Create new project", hint: "Start with Next.js, React, etc." },
7686
- { value: "prd-maker", label: "\u270F\uFE0F Plan my project", hint: "Create a detailed plan first" },
7687
- { value: "build", label: "\u{1F3D7}\uFE0F Build from plan", hint: "I already have a PRD file" },
7688
- { value: "advisors", label: "\u{1F31F} Get expert advice", hint: "AI consultants help you decide" },
7689
- { value: "integrate", label: "\u{1F50C} Add a service", hint: "Stripe, Supabase, Auth, etc." },
7690
- { value: "settings", label: "\u2699\uFE0F Settings", hint: "API keys & preferences" },
7691
- { value: "help", label: "\u2753 Help", hint: "Learn how CodeBakers works" },
7692
- { value: "exit", label: "\u{1F6AA} Return to terminal", hint: "Go back to command line" }
7693
- ]
7680
+ console.log(chalk21.white(" What would you like to do?\n"));
7681
+ console.log(chalk21.green(" 1.") + " \u{1F310} Build a website " + chalk21.dim("- Describe it, AI builds it"));
7682
+ console.log(chalk21.green(" 2.") + " \u{1F195} Create new project " + chalk21.dim("- Start with Next.js, React, etc."));
7683
+ console.log(chalk21.green(" 3.") + " \u270F\uFE0F Plan my project " + chalk21.dim("- Create a detailed plan first"));
7684
+ console.log(chalk21.green(" 4.") + " \u{1F3D7}\uFE0F Build from plan " + chalk21.dim("- I already have a PRD file"));
7685
+ console.log(chalk21.green(" 5.") + " \u{1F31F} Get expert advice " + chalk21.dim("- AI consultants help you decide"));
7686
+ console.log(chalk21.green(" 6.") + " \u{1F50C} Add a service " + chalk21.dim("- Stripe, Supabase, Auth, etc."));
7687
+ console.log(chalk21.green(" 7.") + " \u2699\uFE0F Settings " + chalk21.dim("- API keys & preferences"));
7688
+ console.log(chalk21.green(" 8.") + " \u2753 Help " + chalk21.dim("- Learn how CodeBakers works"));
7689
+ console.log(chalk21.green(" 0.") + " \u{1F6AA} Return to terminal " + chalk21.dim("- Go back to command line"));
7690
+ console.log("");
7691
+ const choice = await p21.text({
7692
+ message: "Enter a number (0-8):",
7693
+ placeholder: "1",
7694
+ validate: (value) => {
7695
+ if (!/^[0-8]$/.test(value) && value !== "") return "Please enter a number 0-8";
7696
+ }
7694
7697
  });
7695
- if (p21.isCancel(action) || action === "exit") {
7696
- console.log("");
7697
- console.log(chalk21.cyan(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
7698
- console.log(chalk21.white(" You're back in the terminal."));
7699
- console.log("");
7700
- console.log(chalk21.dim(" To start CodeBakers again, type:"));
7701
- console.log(chalk21.green(" codebakers"));
7702
- console.log("");
7703
- console.log(chalk21.dim(" Quick commands you can run directly:"));
7704
- console.log(chalk21.dim(" codebakers website") + chalk21.gray(" - Build a website"));
7705
- console.log(chalk21.dim(" codebakers code") + chalk21.gray(" - Code with AI"));
7706
- console.log(chalk21.dim(" codebakers help") + chalk21.gray(" - See all commands"));
7707
- console.log(chalk21.cyan(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
7708
- console.log("");
7698
+ if (p21.isCancel(choice)) {
7709
7699
  keepRunning = false;
7700
+ showExitMessage();
7710
7701
  break;
7711
7702
  }
7712
- await handleAction(action, config);
7713
- console.log("");
7703
+ const num = choice === "" ? "1" : choice;
7704
+ switch (num) {
7705
+ case "0":
7706
+ keepRunning = false;
7707
+ showExitMessage();
7708
+ break;
7709
+ case "1":
7710
+ await handleAction("website", config);
7711
+ break;
7712
+ case "2":
7713
+ await handleAction("new", config);
7714
+ break;
7715
+ case "3":
7716
+ await handleAction("prd-maker", config);
7717
+ break;
7718
+ case "4":
7719
+ await handleAction("build", config);
7720
+ break;
7721
+ case "5":
7722
+ await handleAction("advisors", config);
7723
+ break;
7724
+ case "6":
7725
+ await handleAction("integrate", config);
7726
+ break;
7727
+ case "7":
7728
+ await handleAction("settings", config);
7729
+ break;
7730
+ case "8":
7731
+ await handleAction("help", config);
7732
+ break;
7733
+ }
7734
+ if (keepRunning) {
7735
+ console.log("\n");
7736
+ }
7714
7737
  }
7715
7738
  }
7739
+ function showExitMessage() {
7740
+ console.log("");
7741
+ console.log(chalk21.cyan(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
7742
+ console.log(chalk21.white(" You're back in the terminal."));
7743
+ console.log("");
7744
+ console.log(chalk21.dim(" To start CodeBakers again, type:"));
7745
+ console.log(chalk21.green(" codebakers"));
7746
+ console.log("");
7747
+ console.log(chalk21.dim(" Quick commands you can run directly:"));
7748
+ console.log(chalk21.dim(" codebakers website") + chalk21.gray(" - Build a website"));
7749
+ console.log(chalk21.dim(" codebakers code") + chalk21.gray(" - Code with AI"));
7750
+ console.log(chalk21.dim(" codebakers help") + chalk21.gray(" - See all commands"));
7751
+ console.log(chalk21.cyan(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
7752
+ console.log("");
7753
+ }
7716
7754
  async function showProjectMenu(config) {
7717
- console.log(chalk21.cyan("\n \u2139\uFE0F I found an existing project in this folder."));
7718
- console.log(chalk21.dim(" Use the arrow keys to select an option, then press Enter.\n"));
7755
+ console.log(chalk21.cyan("\n \u2139\uFE0F I found an existing project in this folder.\n"));
7719
7756
  let keepRunning = true;
7720
7757
  while (keepRunning) {
7721
- const action = await p21.select({
7722
- message: "What would you like to do with this project?",
7723
- options: [
7724
- { value: "code", label: "\u{1F4AC} Code with AI", hint: "Tell AI what to build or fix" },
7725
- { value: "deploy", label: "\u{1F680} Deploy to production", hint: "Make your site live" },
7726
- { value: "check", label: "\u{1F50D} Check my code", hint: "Find issues & improvements" },
7727
- { value: "fix", label: "\u{1F527} Fix errors for me", hint: "AI repairs broken code" },
7728
- { value: "integrate", label: "\u{1F50C} Add a service", hint: "Stripe, Supabase, Auth, etc." },
7729
- { value: "generate", label: "\u26A1 Create new files", hint: "Components, pages, APIs" },
7730
- { value: "new", label: "\u{1F195} Start fresh project", hint: "Begin something new" },
7731
- { value: "settings", label: "\u2699\uFE0F Settings", hint: "API keys & preferences" },
7732
- { value: "help", label: "\u2753 Help", hint: "Learn how CodeBakers works" },
7733
- { value: "exit", label: "\u{1F6AA} Return to terminal", hint: "Go back to command line" }
7734
- ]
7758
+ console.log(chalk21.white(" What would you like to do with this project?\n"));
7759
+ console.log(chalk21.green(" 1.") + " \u{1F4AC} Code with AI " + chalk21.dim("- Tell AI what to build or fix"));
7760
+ console.log(chalk21.green(" 2.") + " \u{1F680} Deploy to production " + chalk21.dim("- Make your site live"));
7761
+ console.log(chalk21.green(" 3.") + " \u{1F50D} Check my code " + chalk21.dim("- Find issues & improvements"));
7762
+ console.log(chalk21.green(" 4.") + " \u{1F527} Fix errors for me " + chalk21.dim("- AI repairs broken code"));
7763
+ console.log(chalk21.green(" 5.") + " \u{1F50C} Add a service " + chalk21.dim("- Stripe, Supabase, Auth, etc."));
7764
+ console.log(chalk21.green(" 6.") + " \u26A1 Create new files " + chalk21.dim("- Components, pages, APIs"));
7765
+ console.log(chalk21.green(" 7.") + " \u{1F195} Start fresh project " + chalk21.dim("- Begin something new"));
7766
+ console.log(chalk21.green(" 8.") + " \u2699\uFE0F Settings " + chalk21.dim("- API keys & preferences"));
7767
+ console.log(chalk21.green(" 9.") + " \u2753 Help " + chalk21.dim("- Learn how CodeBakers works"));
7768
+ console.log(chalk21.green(" 0.") + " \u{1F6AA} Return to terminal " + chalk21.dim("- Go back to command line"));
7769
+ console.log("");
7770
+ const choice = await p21.text({
7771
+ message: "Enter a number (0-9):",
7772
+ placeholder: "1",
7773
+ validate: (value) => {
7774
+ if (!/^[0-9]$/.test(value) && value !== "") return "Please enter a number 0-9";
7775
+ }
7735
7776
  });
7736
- if (p21.isCancel(action) || action === "exit") {
7737
- console.log("");
7738
- console.log(chalk21.cyan(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
7739
- console.log(chalk21.white(" You're back in the terminal."));
7740
- console.log("");
7741
- console.log(chalk21.dim(" To start CodeBakers again, type:"));
7742
- console.log(chalk21.green(" codebakers"));
7743
- console.log("");
7744
- console.log(chalk21.dim(" Quick commands you can run directly:"));
7745
- console.log(chalk21.dim(" codebakers code") + chalk21.gray(" - Code with AI"));
7746
- console.log(chalk21.dim(" codebakers deploy") + chalk21.gray(" - Deploy your project"));
7747
- console.log(chalk21.dim(" codebakers help") + chalk21.gray(" - See all commands"));
7748
- console.log(chalk21.cyan(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
7749
- console.log("");
7777
+ if (p21.isCancel(choice)) {
7750
7778
  keepRunning = false;
7779
+ showExitMessage();
7751
7780
  break;
7752
7781
  }
7753
- await handleAction(action, config);
7754
- console.log("");
7782
+ const num = choice === "" ? "1" : choice;
7783
+ switch (num) {
7784
+ case "0":
7785
+ keepRunning = false;
7786
+ showExitMessage();
7787
+ break;
7788
+ case "1":
7789
+ await handleAction("code", config);
7790
+ break;
7791
+ case "2":
7792
+ await handleAction("deploy", config);
7793
+ break;
7794
+ case "3":
7795
+ await handleAction("check", config);
7796
+ break;
7797
+ case "4":
7798
+ await handleAction("fix", config);
7799
+ break;
7800
+ case "5":
7801
+ await handleAction("integrate", config);
7802
+ break;
7803
+ case "6":
7804
+ await handleAction("generate", config);
7805
+ break;
7806
+ case "7":
7807
+ await handleAction("new", config);
7808
+ break;
7809
+ case "8":
7810
+ await handleAction("settings", config);
7811
+ break;
7812
+ case "9":
7813
+ await handleAction("help", config);
7814
+ break;
7815
+ }
7816
+ if (keepRunning) {
7817
+ console.log("\n");
7818
+ }
7755
7819
  }
7756
7820
  }
7757
7821
  async function handleAction(action, config) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebakers",
3
- "version": "2.3.5",
3
+ "version": "2.3.6",
4
4
  "description": "AI dev team that follows the rules. Build apps from anywhere with pattern enforcement.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -30,7 +30,7 @@ import { integrateCommand, INTEGRATIONS } from './commands/integrate.js';
30
30
  import { websiteCommand } from './commands/website.js';
31
31
  import { parseNaturalLanguage } from './utils/nlp.js';
32
32
 
33
- const VERSION = '2.3.5';
33
+ const VERSION = '2.3.6';
34
34
 
35
35
  // ASCII art logo
36
36
  const logo = `
@@ -100,107 +100,168 @@ async function showMainMenu(): Promise<void> {
100
100
  // ============================================================================
101
101
 
102
102
  async function showStartMenu(config: Config): Promise<void> {
103
- // Show helpful context message
104
- console.log(chalk.cyan('\n ℹ️ This folder doesn\'t have a project yet.'));
105
- console.log(chalk.dim(' Use the arrow keys to select an option, then press Enter.\n'));
106
-
103
+ console.log(chalk.cyan('\n ℹ️ This folder doesn\'t have a project yet.\n'));
104
+
107
105
  let keepRunning = true;
108
106
 
109
107
  while (keepRunning) {
110
- const action = await p.select({
111
- message: 'What would you like to do?',
112
- options: [
113
- { value: 'website', label: '🌐 Build a website', hint: 'Describe it, AI builds it' },
114
- { value: 'new', label: '🆕 Create new project', hint: 'Start with Next.js, React, etc.' },
115
- { value: 'prd-maker', label: '✏️ Plan my project', hint: 'Create a detailed plan first' },
116
- { value: 'build', label: '🏗️ Build from plan', hint: 'I already have a PRD file' },
117
- { value: 'advisors', label: '🌟 Get expert advice', hint: 'AI consultants help you decide' },
118
- { value: 'integrate', label: '🔌 Add a service', hint: 'Stripe, Supabase, Auth, etc.' },
119
- { value: 'settings', label: '⚙️ Settings', hint: 'API keys & preferences' },
120
- { value: 'help', label: '❓ Help', hint: 'Learn how CodeBakers works' },
121
- { value: 'exit', label: '🚪 Return to terminal', hint: 'Go back to command line' },
122
- ],
108
+ console.log(chalk.white(' What would you like to do?\n'));
109
+ console.log(chalk.green(' 1.') + ' 🌐 Build a website ' + chalk.dim('- Describe it, AI builds it'));
110
+ console.log(chalk.green(' 2.') + ' 🆕 Create new project ' + chalk.dim('- Start with Next.js, React, etc.'));
111
+ console.log(chalk.green(' 3.') + ' ✏️ Plan my project ' + chalk.dim('- Create a detailed plan first'));
112
+ console.log(chalk.green(' 4.') + ' 🏗️ Build from plan ' + chalk.dim('- I already have a PRD file'));
113
+ console.log(chalk.green(' 5.') + ' 🌟 Get expert advice ' + chalk.dim('- AI consultants help you decide'));
114
+ console.log(chalk.green(' 6.') + ' 🔌 Add a service ' + chalk.dim('- Stripe, Supabase, Auth, etc.'));
115
+ console.log(chalk.green(' 7.') + ' ⚙️ Settings ' + chalk.dim('- API keys & preferences'));
116
+ console.log(chalk.green(' 8.') + ' Help ' + chalk.dim('- Learn how CodeBakers works'));
117
+ console.log(chalk.green(' 0.') + ' 🚪 Return to terminal ' + chalk.dim('- Go back to command line'));
118
+ console.log('');
119
+
120
+ const choice = await p.text({
121
+ message: 'Enter a number (0-8):',
122
+ placeholder: '1',
123
+ validate: (value) => {
124
+ if (!/^[0-8]$/.test(value) && value !== '') return 'Please enter a number 0-8';
125
+ }
123
126
  });
124
127
 
125
- // User pressed Ctrl+C or selected exit
126
- if (p.isCancel(action) || action === 'exit') {
127
- console.log('');
128
- console.log(chalk.cyan(' ─────────────────────────────────────────────────'));
129
- console.log(chalk.white(' You\'re back in the terminal.'));
130
- console.log('');
131
- console.log(chalk.dim(' To start CodeBakers again, type:'));
132
- console.log(chalk.green(' codebakers'));
133
- console.log('');
134
- console.log(chalk.dim(' Quick commands you can run directly:'));
135
- console.log(chalk.dim(' codebakers website') + chalk.gray(' - Build a website'));
136
- console.log(chalk.dim(' codebakers code') + chalk.gray(' - Code with AI'));
137
- console.log(chalk.dim(' codebakers help') + chalk.gray(' - See all commands'));
138
- console.log(chalk.cyan(' ─────────────────────────────────────────────────'));
139
- console.log('');
128
+ if (p.isCancel(choice)) {
140
129
  keepRunning = false;
130
+ showExitMessage();
141
131
  break;
142
132
  }
143
133
 
144
- // Handle the selected action
145
- await handleAction(action as string, config);
134
+ const num = choice === '' ? '1' : choice;
135
+
136
+ switch (num) {
137
+ case '0':
138
+ keepRunning = false;
139
+ showExitMessage();
140
+ break;
141
+ case '1':
142
+ await handleAction('website', config);
143
+ break;
144
+ case '2':
145
+ await handleAction('new', config);
146
+ break;
147
+ case '3':
148
+ await handleAction('prd-maker', config);
149
+ break;
150
+ case '4':
151
+ await handleAction('build', config);
152
+ break;
153
+ case '5':
154
+ await handleAction('advisors', config);
155
+ break;
156
+ case '6':
157
+ await handleAction('integrate', config);
158
+ break;
159
+ case '7':
160
+ await handleAction('settings', config);
161
+ break;
162
+ case '8':
163
+ await handleAction('help', config);
164
+ break;
165
+ }
146
166
 
147
- // Show a brief pause before showing menu again
148
- console.log('');
167
+ if (keepRunning) {
168
+ console.log('\n');
169
+ }
149
170
  }
150
171
  }
151
172
 
173
+ function showExitMessage(): void {
174
+ console.log('');
175
+ console.log(chalk.cyan(' ─────────────────────────────────────────────────'));
176
+ console.log(chalk.white(' You\'re back in the terminal.'));
177
+ console.log('');
178
+ console.log(chalk.dim(' To start CodeBakers again, type:'));
179
+ console.log(chalk.green(' codebakers'));
180
+ console.log('');
181
+ console.log(chalk.dim(' Quick commands you can run directly:'));
182
+ console.log(chalk.dim(' codebakers website') + chalk.gray(' - Build a website'));
183
+ console.log(chalk.dim(' codebakers code') + chalk.gray(' - Code with AI'));
184
+ console.log(chalk.dim(' codebakers help') + chalk.gray(' - See all commands'));
185
+ console.log(chalk.cyan(' ─────────────────────────────────────────────────'));
186
+ console.log('');
187
+ }
188
+
152
189
  // ============================================================================
153
190
  // PROJECT MENU (In a project)
154
191
  // ============================================================================
155
192
 
156
193
  async function showProjectMenu(config: Config): Promise<void> {
157
- // Show helpful context message
158
- console.log(chalk.cyan('\n ℹ️ I found an existing project in this folder.'));
159
- console.log(chalk.dim(' Use the arrow keys to select an option, then press Enter.\n'));
194
+ console.log(chalk.cyan('\n ℹ️ I found an existing project in this folder.\n'));
160
195
 
161
196
  let keepRunning = true;
162
197
 
163
198
  while (keepRunning) {
164
- const action = await p.select({
165
- message: 'What would you like to do with this project?',
166
- options: [
167
- { value: 'code', label: '💬 Code with AI', hint: 'Tell AI what to build or fix' },
168
- { value: 'deploy', label: '🚀 Deploy to production', hint: 'Make your site live' },
169
- { value: 'check', label: '🔍 Check my code', hint: 'Find issues & improvements' },
170
- { value: 'fix', label: '🔧 Fix errors for me', hint: 'AI repairs broken code' },
171
- { value: 'integrate', label: '🔌 Add a service', hint: 'Stripe, Supabase, Auth, etc.' },
172
- { value: 'generate', label: ' Create new files', hint: 'Components, pages, APIs' },
173
- { value: 'new', label: '🆕 Start fresh project', hint: 'Begin something new' },
174
- { value: 'settings', label: '⚙️ Settings', hint: 'API keys & preferences' },
175
- { value: 'help', label: '❓ Help', hint: 'Learn how CodeBakers works' },
176
- { value: 'exit', label: '🚪 Return to terminal', hint: 'Go back to command line' },
177
- ],
199
+ console.log(chalk.white(' What would you like to do with this project?\n'));
200
+ console.log(chalk.green(' 1.') + ' 💬 Code with AI ' + chalk.dim('- Tell AI what to build or fix'));
201
+ console.log(chalk.green(' 2.') + ' 🚀 Deploy to production ' + chalk.dim('- Make your site live'));
202
+ console.log(chalk.green(' 3.') + ' 🔍 Check my code ' + chalk.dim('- Find issues & improvements'));
203
+ console.log(chalk.green(' 4.') + ' 🔧 Fix errors for me ' + chalk.dim('- AI repairs broken code'));
204
+ console.log(chalk.green(' 5.') + ' 🔌 Add a service ' + chalk.dim('- Stripe, Supabase, Auth, etc.'));
205
+ console.log(chalk.green(' 6.') + ' Create new files ' + chalk.dim('- Components, pages, APIs'));
206
+ console.log(chalk.green(' 7.') + ' 🆕 Start fresh project ' + chalk.dim('- Begin something new'));
207
+ console.log(chalk.green(' 8.') + ' ⚙️ Settings ' + chalk.dim('- API keys & preferences'));
208
+ console.log(chalk.green(' 9.') + ' Help ' + chalk.dim('- Learn how CodeBakers works'));
209
+ console.log(chalk.green(' 0.') + ' 🚪 Return to terminal ' + chalk.dim('- Go back to command line'));
210
+ console.log('');
211
+
212
+ const choice = await p.text({
213
+ message: 'Enter a number (0-9):',
214
+ placeholder: '1',
215
+ validate: (value) => {
216
+ if (!/^[0-9]$/.test(value) && value !== '') return 'Please enter a number 0-9';
217
+ }
178
218
  });
179
219
 
180
- // User pressed Ctrl+C or selected exit
181
- if (p.isCancel(action) || action === 'exit') {
182
- console.log('');
183
- console.log(chalk.cyan(' ─────────────────────────────────────────────────'));
184
- console.log(chalk.white(' You\'re back in the terminal.'));
185
- console.log('');
186
- console.log(chalk.dim(' To start CodeBakers again, type:'));
187
- console.log(chalk.green(' codebakers'));
188
- console.log('');
189
- console.log(chalk.dim(' Quick commands you can run directly:'));
190
- console.log(chalk.dim(' codebakers code') + chalk.gray(' - Code with AI'));
191
- console.log(chalk.dim(' codebakers deploy') + chalk.gray(' - Deploy your project'));
192
- console.log(chalk.dim(' codebakers help') + chalk.gray(' - See all commands'));
193
- console.log(chalk.cyan(' ─────────────────────────────────────────────────'));
194
- console.log('');
220
+ if (p.isCancel(choice)) {
195
221
  keepRunning = false;
222
+ showExitMessage();
196
223
  break;
197
224
  }
198
225
 
199
- // Handle the selected action
200
- await handleAction(action as string, config);
226
+ const num = choice === '' ? '1' : choice;
227
+
228
+ switch (num) {
229
+ case '0':
230
+ keepRunning = false;
231
+ showExitMessage();
232
+ break;
233
+ case '1':
234
+ await handleAction('code', config);
235
+ break;
236
+ case '2':
237
+ await handleAction('deploy', config);
238
+ break;
239
+ case '3':
240
+ await handleAction('check', config);
241
+ break;
242
+ case '4':
243
+ await handleAction('fix', config);
244
+ break;
245
+ case '5':
246
+ await handleAction('integrate', config);
247
+ break;
248
+ case '6':
249
+ await handleAction('generate', config);
250
+ break;
251
+ case '7':
252
+ await handleAction('new', config);
253
+ break;
254
+ case '8':
255
+ await handleAction('settings', config);
256
+ break;
257
+ case '9':
258
+ await handleAction('help', config);
259
+ break;
260
+ }
201
261
 
202
- // Show a brief pause before showing menu again
203
- console.log('');
262
+ if (keepRunning) {
263
+ console.log('\n');
264
+ }
204
265
  }
205
266
  }
206
267