@codebakers/cli 3.9.19 → 3.9.21

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.
@@ -2158,9 +2158,17 @@ phase: setup
2158
2158
  results.push(...deployResults);
2159
2159
  }
2160
2160
  else {
2161
+ // Check for missing services and offer setup help
2162
+ const serviceCheck = this.checkMissingServices(cwd);
2163
+ results.push('### šŸ”§ Service Configuration\n');
2164
+ if (serviceCheck.missing.length > 0) {
2165
+ results.push(`Missing configuration for: **${serviceCheck.missing.join(', ')}**\n`);
2166
+ results.push('Run `setup_services` for step-by-step instructions to get your API keys.');
2167
+ results.push('You can paste your keys in chat and I\'ll add them to `.env.local` for you!\n');
2168
+ }
2161
2169
  results.push('### Next Steps:\n');
2162
- results.push('1. **Set up Supabase:** Go to https://supabase.com and create a free project');
2163
- results.push('2. **Add credentials:** Copy your Supabase URL and anon key to `.env.local`');
2170
+ results.push('1. **Configure services:** Run `setup_services` to set up Supabase, OpenAI, etc.');
2171
+ results.push('2. **Paste your keys:** Get your API keys and paste them in chat');
2164
2172
  results.push('3. **Start building:** Just tell me what features you want!\n');
2165
2173
  results.push('### Example:\n');
2166
2174
  results.push('> "Add user authentication with email/password"');
@@ -2559,6 +2567,15 @@ You cannot write code without calling this tool first.
2559
2567
  results.push('3. Call `validate_complete` before marking done');
2560
2568
  results.push('4. Server verifies compliance\n');
2561
2569
  results.push('No local pattern files needed - everything is server-side!');
2570
+ // Check for missing services and offer setup help
2571
+ const serviceCheck = this.checkMissingServices(cwd);
2572
+ if (serviceCheck.missing.length > 0) {
2573
+ results.push('\n---\n');
2574
+ results.push('## šŸ”§ Service Configuration\n');
2575
+ results.push(`Missing configuration for: **${serviceCheck.missing.join(', ')}**\n`);
2576
+ results.push('Run `setup_services` to get step-by-step instructions for getting your API keys.');
2577
+ results.push('You can paste your keys in chat and I\'ll add them to `.env.local` for you!');
2578
+ }
2562
2579
  }
2563
2580
  catch (error) {
2564
2581
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -2571,6 +2588,46 @@ You cannot write code without calling this tool first.
2571
2588
  }],
2572
2589
  };
2573
2590
  }
2591
+ /**
2592
+ * Check which services are missing from .env
2593
+ */
2594
+ checkMissingServices(cwd) {
2595
+ const SERVICE_ENV_VARS = {
2596
+ 'Supabase': ['NEXT_PUBLIC_SUPABASE_URL', 'NEXT_PUBLIC_SUPABASE_ANON_KEY'],
2597
+ 'OpenAI': ['OPENAI_API_KEY'],
2598
+ 'Anthropic': ['ANTHROPIC_API_KEY'],
2599
+ };
2600
+ // Read .env file
2601
+ const envPath = path.join(cwd, '.env');
2602
+ const envLocalPath = path.join(cwd, '.env.local');
2603
+ let envContent = '';
2604
+ if (fs.existsSync(envLocalPath)) {
2605
+ envContent = fs.readFileSync(envLocalPath, 'utf-8');
2606
+ }
2607
+ else if (fs.existsSync(envPath)) {
2608
+ envContent = fs.readFileSync(envPath, 'utf-8');
2609
+ }
2610
+ // Parse existing env vars
2611
+ const existingVars = new Set();
2612
+ for (const line of envContent.split('\n')) {
2613
+ const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
2614
+ if (match) {
2615
+ existingVars.add(match[1]);
2616
+ }
2617
+ }
2618
+ const missing = [];
2619
+ const configured = [];
2620
+ for (const [service, vars] of Object.entries(SERVICE_ENV_VARS)) {
2621
+ const hasMissing = vars.some(v => !existingVars.has(v));
2622
+ if (hasMissing) {
2623
+ missing.push(service);
2624
+ }
2625
+ else {
2626
+ configured.push(service);
2627
+ }
2628
+ }
2629
+ return { missing, configured };
2630
+ }
2574
2631
  handleSetExperienceLevel(args) {
2575
2632
  const { level } = args;
2576
2633
  // Validate level
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebakers/cli",
3
- "version": "3.9.19",
3
+ "version": "3.9.21",
4
4
  "description": "CodeBakers CLI - Production patterns for AI-assisted development",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/mcp/server.ts CHANGED
@@ -2480,9 +2480,19 @@ phase: setup
2480
2480
  const deployResults = await this.executeFullDeploy(projectName, cwd, description);
2481
2481
  results.push(...deployResults);
2482
2482
  } else {
2483
+ // Check for missing services and offer setup help
2484
+ const serviceCheck = this.checkMissingServices(cwd);
2485
+
2486
+ results.push('### šŸ”§ Service Configuration\n');
2487
+ if (serviceCheck.missing.length > 0) {
2488
+ results.push(`Missing configuration for: **${serviceCheck.missing.join(', ')}**\n`);
2489
+ results.push('Run `setup_services` for step-by-step instructions to get your API keys.');
2490
+ results.push('You can paste your keys in chat and I\'ll add them to `.env.local` for you!\n');
2491
+ }
2492
+
2483
2493
  results.push('### Next Steps:\n');
2484
- results.push('1. **Set up Supabase:** Go to https://supabase.com and create a free project');
2485
- results.push('2. **Add credentials:** Copy your Supabase URL and anon key to `.env.local`');
2494
+ results.push('1. **Configure services:** Run `setup_services` to set up Supabase, OpenAI, etc.');
2495
+ results.push('2. **Paste your keys:** Get your API keys and paste them in chat');
2486
2496
  results.push('3. **Start building:** Just tell me what features you want!\n');
2487
2497
  results.push('### Example:\n');
2488
2498
  results.push('> "Add user authentication with email/password"');
@@ -2907,6 +2917,16 @@ You cannot write code without calling this tool first.
2907
2917
  results.push('4. Server verifies compliance\n');
2908
2918
  results.push('No local pattern files needed - everything is server-side!');
2909
2919
 
2920
+ // Check for missing services and offer setup help
2921
+ const serviceCheck = this.checkMissingServices(cwd);
2922
+ if (serviceCheck.missing.length > 0) {
2923
+ results.push('\n---\n');
2924
+ results.push('## šŸ”§ Service Configuration\n');
2925
+ results.push(`Missing configuration for: **${serviceCheck.missing.join(', ')}**\n`);
2926
+ results.push('Run `setup_services` to get step-by-step instructions for getting your API keys.');
2927
+ results.push('You can paste your keys in chat and I\'ll add them to `.env.local` for you!');
2928
+ }
2929
+
2910
2930
  } catch (error) {
2911
2931
  const message = error instanceof Error ? error.message : 'Unknown error';
2912
2932
  results.push(`\nāŒ Error: ${message}`);
@@ -2920,6 +2940,51 @@ You cannot write code without calling this tool first.
2920
2940
  };
2921
2941
  }
2922
2942
 
2943
+ /**
2944
+ * Check which services are missing from .env
2945
+ */
2946
+ private checkMissingServices(cwd: string): { missing: string[]; configured: string[] } {
2947
+ const SERVICE_ENV_VARS: Record<string, string[]> = {
2948
+ 'Supabase': ['NEXT_PUBLIC_SUPABASE_URL', 'NEXT_PUBLIC_SUPABASE_ANON_KEY'],
2949
+ 'OpenAI': ['OPENAI_API_KEY'],
2950
+ 'Anthropic': ['ANTHROPIC_API_KEY'],
2951
+ };
2952
+
2953
+ // Read .env file
2954
+ const envPath = path.join(cwd, '.env');
2955
+ const envLocalPath = path.join(cwd, '.env.local');
2956
+ let envContent = '';
2957
+
2958
+ if (fs.existsSync(envLocalPath)) {
2959
+ envContent = fs.readFileSync(envLocalPath, 'utf-8');
2960
+ } else if (fs.existsSync(envPath)) {
2961
+ envContent = fs.readFileSync(envPath, 'utf-8');
2962
+ }
2963
+
2964
+ // Parse existing env vars
2965
+ const existingVars = new Set<string>();
2966
+ for (const line of envContent.split('\n')) {
2967
+ const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
2968
+ if (match) {
2969
+ existingVars.add(match[1]);
2970
+ }
2971
+ }
2972
+
2973
+ const missing: string[] = [];
2974
+ const configured: string[] = [];
2975
+
2976
+ for (const [service, vars] of Object.entries(SERVICE_ENV_VARS)) {
2977
+ const hasMissing = vars.some(v => !existingVars.has(v));
2978
+ if (hasMissing) {
2979
+ missing.push(service);
2980
+ } else {
2981
+ configured.push(service);
2982
+ }
2983
+ }
2984
+
2985
+ return { missing, configured };
2986
+ }
2987
+
2923
2988
  private handleSetExperienceLevel(args: { level: ExperienceLevel }) {
2924
2989
  const { level } = args;
2925
2990