codebakers 2.5.0 → 2.5.4

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  prdCommand
3
- } from "./chunk-WZQNFV7Q.js";
3
+ } from "./chunk-LANM5XQW.js";
4
4
  import "./chunk-ASIJIQYC.js";
5
5
  export {
6
6
  prdCommand
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebakers",
3
- "version": "2.5.0",
3
+ "version": "2.5.4",
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",
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import Anthropic from '@anthropic-ai/sdk';
6
6
  import { Config } from '../utils/config.js';
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import Anthropic from '@anthropic-ai/sdk';
6
6
  import { execa } from 'execa';
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import glob from 'fast-glob';
6
6
  import { Config } from '../utils/config.js';
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import Anthropic from '@anthropic-ai/sdk';
6
6
  import { execa } from 'execa';
@@ -1,7 +1,7 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
3
  import { execa } from 'execa';
4
- import * as fs from 'fs-extra';
4
+ import fs from 'fs-extra';
5
5
  import * as path from 'path';
6
6
  import Anthropic from '@anthropic-ai/sdk';
7
7
  import { Config } from '../utils/config.js';
@@ -230,7 +230,7 @@ ${chalk.bold('Type:')} ${deployType}
230
230
  ${chalk.bold('Time:')} ${new Date().toLocaleTimeString()}
231
231
 
232
232
  ${chalk.dim('View in Vercel Dashboard:')}
233
- ${chalk.dim(deployment.dashboardUrl || 'https://vercel.com/dashboard')}
233
+ ${chalk.dim('https://vercel.com/dashboard')}
234
234
  `));
235
235
 
236
236
  } catch (error) {
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import { Config } from '../utils/config.js';
6
6
 
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
 
6
6
  export async function generateCommand(type?: string): Promise<void> {
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import { execa } from 'execa';
6
6
  import { Config } from '../utils/config.js';
@@ -364,7 +364,14 @@ async function createLocalProject(
364
364
  await fs.ensureDir(path.join(projectPath, 'src', 'services'));
365
365
 
366
366
  // Create package.json
367
- const packageJson = {
367
+ const packageJson: {
368
+ name: string;
369
+ version: string;
370
+ private: boolean;
371
+ scripts: Record<string, string>;
372
+ dependencies: Record<string, string>;
373
+ devDependencies: Record<string, string>;
374
+ } = {
368
375
  name: path.basename(projectPath),
369
376
  version: '0.1.0',
370
377
  private: true,
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import open from 'open';
6
6
  import { Config } from '../utils/config.js';
@@ -1,7 +1,7 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
3
  import { execa } from 'execa';
4
- import * as fs from 'fs-extra';
4
+ import fs from 'fs-extra';
5
5
  import * as path from 'path';
6
6
  import { Config } from '../utils/config.js';
7
7
 
@@ -1,10 +1,11 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import Anthropic from '@anthropic-ai/sdk';
6
+ import { execa } from 'execa';
6
7
  import { Config } from '../utils/config.js';
7
- import { textWithVoice, getVoiceInput, checkVoiceAvailability } from '../utils/voice.js';
8
+ import { textWithVoice } from '../utils/voice.js';
8
9
 
9
10
  interface PRDInput {
10
11
  projectName: string;
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import Anthropic from '@anthropic-ai/sdk';
6
6
  import { Config } from '../utils/config.js';
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import glob from 'fast-glob';
5
5
  import * as path from 'path';
6
6
 
@@ -1,7 +1,7 @@
1
1
  // src/commands/status.ts
2
2
  import * as p from '@clack/prompts';
3
3
  import chalk from 'chalk';
4
- import * as fs from 'fs-extra';
4
+ import fs from 'fs-extra';
5
5
  import * as path from 'path';
6
6
  import { Config } from '../utils/config.js';
7
7
 
@@ -1,12 +1,22 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import Anthropic from '@anthropic-ai/sdk';
6
6
  import { execa } from 'execa';
7
7
  import { Config } from '../utils/config.js';
8
8
  import { textWithVoice } from '../utils/voice.js';
9
9
  import { StepTracker, showError, showSuccess, showFileList, ERRORS } from '../utils/display.js';
10
+ import {
11
+ showMiniLogo,
12
+ box,
13
+ doubleBox,
14
+ sectionHeader,
15
+ showSuccessScreen,
16
+ showErrorScreen,
17
+ showFileTree,
18
+ colors
19
+ } from '../utils/ui.js';
10
20
 
11
21
  // ============================================================================
12
22
  // WEBSITE TEMPLATES
@@ -136,39 +146,37 @@ export async function websiteCommand(): Promise<void> {
136
146
  const config = new Config();
137
147
 
138
148
  if (!config.isConfigured()) {
139
- console.log(chalk.yellow(`
140
- ⚠️ CodeBakers isn't set up yet.
141
-
142
- Run this first:
143
- ${chalk.cyan('codebakers setup')}
144
- `));
149
+ showErrorScreen({
150
+ title: 'CodeBakers not configured',
151
+ message: 'Run setup first to connect your API keys.',
152
+ command: 'codebakers setup',
153
+ });
145
154
  return;
146
155
  }
147
156
 
148
157
  const anthropicCreds = config.getCredentials('anthropic');
149
158
  if (!anthropicCreds?.apiKey) {
150
- console.log(chalk.yellow(`
151
- ⚠️ Anthropic API key not configured.
152
-
153
- The website builder needs Claude AI to generate code.
154
-
155
- Run this to add your API key:
156
- ${chalk.cyan('codebakers setup')}
157
-
158
- Get an API key at:
159
- ${chalk.dim('https://console.anthropic.com/settings/keys')}
160
- `));
159
+ showErrorScreen({
160
+ title: 'Anthropic API key not configured',
161
+ message: 'The website builder needs Claude AI to generate code.',
162
+ fixes: [
163
+ 'Run: codebakers setup',
164
+ 'Get an API key at: console.anthropic.com',
165
+ ],
166
+ command: 'codebakers setup',
167
+ });
161
168
  return;
162
169
  }
163
170
 
164
- console.log(chalk.cyan(`
165
- ╔═══════════════════════════════════════════════════════════════╗
166
- 🌐 WEBSITE BUILDER ║
167
- ║ ║
168
- ║ Describe your website in plain English. ║
169
- ║ AI builds it in minutes. ║
170
- ╚═══════════════════════════════════════════════════════════════╝
171
- `));
171
+ console.clear();
172
+ showMiniLogo();
173
+
174
+ doubleBox([
175
+ colors.primary('🌐 WEBSITE BUILDER'),
176
+ '',
177
+ colors.white('Describe your website in plain English.'),
178
+ colors.muted('AI builds it in minutes.'),
179
+ ]);
172
180
 
173
181
  // Step 1: Choose approach
174
182
  const approach = await p.select({
@@ -689,21 +697,21 @@ Make it production-quality and visually impressive.`
689
697
 
690
698
  // Show created files
691
699
  if (createdFiles.length > 0) {
692
- showFileList('Files created', createdFiles.slice(0, 10));
700
+ showFileTree('Files created', createdFiles.slice(0, 10));
693
701
  if (createdFiles.length > 10) {
694
- console.log(chalk.dim(` ... and ${createdFiles.length - 10} more files`));
702
+ console.log(colors.muted(` ... and ${createdFiles.length - 10} more files`));
695
703
  }
696
704
  }
697
705
 
698
- // Success message
699
- showSuccess({
706
+ // Success message with beautiful screen
707
+ showSuccessScreen({
700
708
  title: 'Website built successfully!',
701
709
  message: spec.description,
702
710
  stats: [
703
711
  { label: 'Project', value: spec.name },
704
- { label: 'Files created', value: createdFiles.length.toString() },
712
+ { label: 'Files', value: createdFiles.length.toString() + ' created' },
705
713
  { label: 'Sections', value: spec.sections.length.toString() },
706
- { label: 'Build time', value: steps.getElapsedTime() },
714
+ { label: 'Time', value: steps.getElapsedTime() },
707
715
  ],
708
716
  nextSteps: [
709
717
  `cd ${spec.name}`,
@@ -719,7 +727,7 @@ Make it production-quality and visually impressive.`
719
727
  });
720
728
 
721
729
  if (openDev && !p.isCancel(openDev)) {
722
- console.log(chalk.dim('\n Starting dev server...\n'));
730
+ console.log(colors.muted('\n Starting dev server...\n'));
723
731
 
724
732
  // Change to project directory and run dev
725
733
  process.chdir(projectPath);
package/src/index.ts CHANGED
@@ -29,18 +29,21 @@ import { buildCommand } from './commands/build.js';
29
29
  import { integrateCommand, INTEGRATIONS } from './commands/integrate.js';
30
30
  import { websiteCommand } from './commands/website.js';
31
31
  import { parseNaturalLanguage } from './utils/nlp.js';
32
-
33
- const VERSION = '2.5.0';
34
-
35
- // ASCII art logo
36
- const logo = `
37
- ██████╗ ██████╗ ██████╗ ███████╗██████╗ █████╗ ██╗ ██╗███████╗██████╗ ███████╗
38
- ██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗██╔══██╗██║ ██╔╝██╔════╝██╔══██╗██╔════╝
39
- ██║ ██║ ██║██║ ██║█████╗ ██████╔╝███████║█████╔╝ █████╗ ██████╔╝███████╗
40
- ██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗██╔══██║██╔═██╗ ██╔══╝ ██╔══██╗╚════██║
41
- ╚██████╗╚██████╔╝██████╔╝███████╗██████╔╝██║ ██║██║ ██╗███████╗██║ ██║███████║
42
- ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝
43
- `;
32
+ import {
33
+ showLogo,
34
+ showMiniLogo,
35
+ showMenuCards,
36
+ showSuccessScreen,
37
+ showErrorScreen,
38
+ box,
39
+ doubleBox,
40
+ divider,
41
+ sectionHeader,
42
+ colors,
43
+ headerGradient
44
+ } from './utils/ui.js';
45
+
46
+ const VERSION = '2.5.4';
44
47
 
45
48
  // ============================================================================
46
49
  // MAIN MENU
@@ -49,21 +52,23 @@ const logo = `
49
52
  async function showMainMenu(): Promise<void> {
50
53
  const config = new Config();
51
54
 
52
- // Show logo
53
- console.log(gradient.pastel.multiline(logo));
54
- console.log(chalk.dim(` v${VERSION} — AI dev team that follows the rules\n`));
55
+ // Clear screen and show beautiful logo
56
+ console.clear();
57
+ showLogo();
58
+ console.log(colors.muted(` v${VERSION}`));
59
+ console.log('');
55
60
 
56
61
  // Check setup status
57
62
  const hasAnthropic = !!config.getCredentials('anthropic')?.apiKey;
58
63
 
59
64
  // STEP 1: First time? Run setup
60
65
  if (!hasAnthropic) {
61
- console.log(boxen(
62
- chalk.yellow('Welcome to CodeBakers!\n\n') +
63
- chalk.white('Let\'s connect your Anthropic API key so the AI can work.\n') +
64
- chalk.dim('(Takes about 1 minute)'),
65
- { padding: 1, borderColor: 'yellow', borderStyle: 'round' }
66
- ));
66
+ doubleBox([
67
+ colors.warning('👋 Welcome to CodeBakers!'),
68
+ '',
69
+ colors.white("Let's connect your Anthropic API key so the AI can work."),
70
+ colors.muted('(Takes about 1 minute)'),
71
+ ], 'default');
67
72
 
68
73
  await setupCommand();
69
74
 
@@ -81,14 +86,18 @@ async function showMainMenu(): Promise<void> {
81
86
  // Show context
82
87
  if (inProject && projectConfig) {
83
88
  const framework = projectConfig.framework || 'detected';
84
- console.log(chalk.cyan(` 📁 Working in: ${chalk.bold(folderName)}`));
85
- console.log(chalk.dim(` ${framework} project\n`));
89
+ box([
90
+ colors.secondary('📁 ') + colors.white(folderName),
91
+ colors.muted(` ${framework} project`),
92
+ ]);
86
93
 
87
94
  // SHOW PROJECT MENU
88
95
  await showProjectMenu(config);
89
96
  } else {
90
- console.log(chalk.cyan(` 📁 Current folder: ${chalk.bold(cwd)}`));
91
- console.log(chalk.dim(` Not a project folder\n`));
97
+ box([
98
+ colors.secondary('📁 ') + colors.white(cwd),
99
+ colors.muted(' Not a project folder'),
100
+ ]);
92
101
 
93
102
  // SHOW START MENU
94
103
  await showStartMenu(config);
@@ -100,25 +109,28 @@ async function showMainMenu(): Promise<void> {
100
109
  // ============================================================================
101
110
 
102
111
  async function showStartMenu(config: Config): Promise<void> {
103
- console.log(chalk.cyan('\n ℹ️ This folder doesn\'t have a project yet.\n'));
112
+ console.log(colors.muted(' This folder doesn\'t have a project yet.'));
113
+ console.log('');
104
114
 
105
115
  let keepRunning = true;
106
116
 
107
117
  while (keepRunning) {
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('');
118
+ sectionHeader('What would you like to do?');
119
+
120
+ showMenuCards([
121
+ { key: '1', icon: '🌐', label: 'Build a Website', description: 'Describe it, AI builds it' },
122
+ { key: '2', icon: '🆕', label: 'Create New Project', description: 'Start with Next.js, React' },
123
+ { key: '3', icon: '✏️', label: 'Plan My Project', description: 'Create a detailed plan' },
124
+ { key: '4', icon: '🏗️', label: 'Build from Plan', description: 'I have a PRD file' },
125
+ { key: '5', icon: '🌟', label: 'Get Expert Advice', description: 'AI consultants help' },
126
+ { key: '6', icon: '🔌', label: 'Add a Service', description: 'Stripe, Supabase, Auth' },
127
+ { key: '7', icon: '⚙️', label: 'Settings', description: 'API keys & preferences' },
128
+ { key: '8', icon: '❓', label: 'Help', description: 'Learn how it works' },
129
+ { key: '0', icon: '🚪', label: 'Exit', description: 'Return to terminal' },
130
+ ]);
119
131
 
120
132
  const choice = await p.text({
121
- message: 'Enter a number (0-8):',
133
+ message: colors.primary('Enter a number (0-8):'),
122
134
  placeholder: '1',
123
135
  validate: (value) => {
124
136
  if (!/^[0-8]$/.test(value) && value !== '') return 'Please enter a number 0-8';
@@ -172,11 +184,11 @@ async function showStartMenu(config: Config): Promise<void> {
172
184
 
173
185
  function showExitMessage(): void {
174
186
  console.log('');
175
- console.log(chalk.cyan(' ─────────────────────────────────────────────────'));
176
- console.log(chalk.white(' You\'re back in the terminal.'));
187
+ divider();
188
+ console.log(colors.white(' You\'re back in the terminal.'));
177
189
  console.log('');
178
- console.log(chalk.dim(' To start CodeBakers again, type:'));
179
- console.log(chalk.green(' codebakers'));
190
+ console.log(colors.muted(' To start CodeBakers again, type:'));
191
+ console.log(colors.success(' codebakers'));
180
192
  console.log('');
181
193
  console.log(chalk.dim(' Quick commands you can run directly:'));
182
194
  console.log(chalk.dim(' codebakers website') + chalk.gray(' - Build a website'));
@@ -1,4 +1,4 @@
1
- import * as fs from 'fs-extra';
1
+ import fs from 'fs-extra';
2
2
  import * as path from 'path';
3
3
  import { Config } from '../utils/config.js';
4
4
 
@@ -1,5 +1,18 @@
1
1
  import chalk from 'chalk';
2
2
 
3
+ // ============================================================================
4
+ // ANTHROPIC RESPONSE HELPER
5
+ // ============================================================================
6
+
7
+ /**
8
+ * Safely extract text from Anthropic API response
9
+ */
10
+ export function getResponseText(response: { content: Array<{ type: string; text?: string }> }): string {
11
+ const firstContent = response.content?.[0];
12
+ if (!firstContent) return '';
13
+ return firstContent.type === 'text' && firstContent.text ? firstContent.text : '';
14
+ }
15
+
3
16
  // ============================================================================
4
17
  // STEP TRACKER - Shows progress through multiple steps
5
18
  // ============================================================================
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
- import * as fs from 'fs-extra';
3
+ import fs from 'fs-extra';
4
4
  import * as path from 'path';
5
5
  import { execa } from 'execa';
6
6