codebakers 2.3.7 → 2.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +409 -427
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/utils/updates.ts +2 -21
package/dist/index.js
CHANGED
|
@@ -12,37 +12,19 @@ import {
|
|
|
12
12
|
// src/index.ts
|
|
13
13
|
import { Command } from "commander";
|
|
14
14
|
import * as p21 from "@clack/prompts";
|
|
15
|
-
import
|
|
15
|
+
import chalk20 from "chalk";
|
|
16
16
|
import boxen2 from "boxen";
|
|
17
17
|
import gradient from "gradient-string";
|
|
18
18
|
import * as path16 from "path";
|
|
19
19
|
|
|
20
20
|
// src/utils/updates.ts
|
|
21
|
-
import chalk from "chalk";
|
|
22
|
-
var VERSION = "1.0.0";
|
|
23
21
|
async function checkForUpdates() {
|
|
24
|
-
|
|
25
|
-
const response = await fetch("https://registry.npmjs.org/codebakers/latest", {
|
|
26
|
-
signal: AbortSignal.timeout(3e3)
|
|
27
|
-
});
|
|
28
|
-
if (!response.ok) return;
|
|
29
|
-
const data = await response.json();
|
|
30
|
-
const latestVersion = data.version;
|
|
31
|
-
if (latestVersion && latestVersion !== VERSION) {
|
|
32
|
-
console.log(chalk.yellow(`
|
|
33
|
-
\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E
|
|
34
|
-
\u2502 Update available: ${VERSION} \u2192 ${latestVersion.padEnd(10)} \u2502
|
|
35
|
-
\u2502 Run: npm install -g codebakers \u2502
|
|
36
|
-
\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F
|
|
37
|
-
`));
|
|
38
|
-
}
|
|
39
|
-
} catch {
|
|
40
|
-
}
|
|
22
|
+
return;
|
|
41
23
|
}
|
|
42
24
|
|
|
43
25
|
// src/commands/setup.ts
|
|
44
26
|
import * as p from "@clack/prompts";
|
|
45
|
-
import
|
|
27
|
+
import chalk from "chalk";
|
|
46
28
|
import boxen from "boxen";
|
|
47
29
|
import open from "open";
|
|
48
30
|
var SERVICES = {
|
|
@@ -254,14 +236,14 @@ async function setupCommand() {
|
|
|
254
236
|
return;
|
|
255
237
|
}
|
|
256
238
|
console.log(boxen(
|
|
257
|
-
|
|
239
|
+
chalk.bold.cyan("Welcome to CodeBakers Setup!\n\n") + chalk.white("We need to connect a few services to get started.\n\n") + chalk.dim("Your credentials are stored locally on your computer\n") + chalk.dim("in ~/.codebakers/ and never sent to our servers.\n\n") + chalk.yellow("Required: ") + chalk.white("Anthropic API key (for AI)\n") + chalk.dim("Optional: GitHub, Vercel, Supabase (for full features)"),
|
|
258
240
|
{ padding: 1, borderColor: "cyan", borderStyle: "round" }
|
|
259
241
|
));
|
|
260
|
-
console.log(
|
|
261
|
-
console.log(
|
|
262
|
-
console.log(
|
|
263
|
-
console.log(
|
|
264
|
-
console.log(
|
|
242
|
+
console.log(chalk.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
243
|
+
console.log(chalk.bold.cyan(" STEP 1 of 4: Anthropic API Key (Required)"));
|
|
244
|
+
console.log(chalk.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
245
|
+
console.log(chalk.white(" Anthropic (Claude)"));
|
|
246
|
+
console.log(chalk.dim(" Powers the AI coding agent\n"));
|
|
265
247
|
const hasAccount = await p.select({
|
|
266
248
|
message: "Do you have an Anthropic account?",
|
|
267
249
|
options: [
|
|
@@ -273,27 +255,27 @@ async function setupCommand() {
|
|
|
273
255
|
return;
|
|
274
256
|
}
|
|
275
257
|
if (hasAccount === "no") {
|
|
276
|
-
console.log(
|
|
277
|
-
console.log(
|
|
278
|
-
console.log(
|
|
279
|
-
console.log(
|
|
280
|
-
console.log(
|
|
281
|
-
console.log(
|
|
282
|
-
console.log(
|
|
258
|
+
console.log(chalk.yellow("\n No problem! Let's get you signed up.\n"));
|
|
259
|
+
console.log(chalk.white(" Steps:"));
|
|
260
|
+
console.log(chalk.cyan(" 1. ") + 'Click "Sign Up" on the page that opens');
|
|
261
|
+
console.log(chalk.cyan(" 2. ") + "Create your account (email + password)");
|
|
262
|
+
console.log(chalk.cyan(" 3. ") + "Once logged in, go to Settings \u2192 API Keys");
|
|
263
|
+
console.log(chalk.cyan(" 4. ") + 'Click "Create Key"');
|
|
264
|
+
console.log(chalk.cyan(" 5. ") + "Copy the key and paste it here\n");
|
|
283
265
|
const openSignup = await p.confirm({
|
|
284
266
|
message: "Open Anthropic signup page?",
|
|
285
267
|
initialValue: true
|
|
286
268
|
});
|
|
287
269
|
if (openSignup && !p.isCancel(openSignup)) {
|
|
288
270
|
await open("https://console.anthropic.com/");
|
|
289
|
-
console.log(
|
|
271
|
+
console.log(chalk.dim("\n Take your time - come back when you have your API key.\n"));
|
|
290
272
|
}
|
|
291
273
|
} else {
|
|
292
|
-
console.log(
|
|
293
|
-
console.log(
|
|
294
|
-
console.log(
|
|
295
|
-
console.log(
|
|
296
|
-
console.log(
|
|
274
|
+
console.log(chalk.bold.white("\n Here's what to do:\n"));
|
|
275
|
+
console.log(chalk.cyan(" 1. ") + "Log in to Anthropic Console");
|
|
276
|
+
console.log(chalk.cyan(" 2. ") + "Go to Settings \u2192 API Keys");
|
|
277
|
+
console.log(chalk.cyan(" 3. ") + 'Click "Create Key"');
|
|
278
|
+
console.log(chalk.cyan(" 4. ") + "Copy the key (starts with sk-ant-)");
|
|
297
279
|
console.log("");
|
|
298
280
|
const openBrowser = await p.confirm({
|
|
299
281
|
message: "Open Anthropic Console?",
|
|
@@ -314,36 +296,36 @@ async function setupCommand() {
|
|
|
314
296
|
}
|
|
315
297
|
});
|
|
316
298
|
if (p.isCancel(apiKey) || !apiKey) {
|
|
317
|
-
console.log(
|
|
318
|
-
console.log(
|
|
299
|
+
console.log(chalk.red("\n \u274C Anthropic API key is required to use CodeBakers."));
|
|
300
|
+
console.log(chalk.dim(" Run `codebakers setup` when you're ready to try again.\n"));
|
|
319
301
|
return;
|
|
320
302
|
}
|
|
321
303
|
config.setCredentials("anthropic", { apiKey });
|
|
322
|
-
console.log(
|
|
323
|
-
console.log(
|
|
324
|
-
console.log(
|
|
325
|
-
console.log(
|
|
304
|
+
console.log(chalk.green("\n \u2713 Anthropic connected successfully!\n"));
|
|
305
|
+
console.log(chalk.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
306
|
+
console.log(chalk.bold.cyan(" STEP 2 of 4: GitHub Token (Recommended)"));
|
|
307
|
+
console.log(chalk.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
326
308
|
await connectServiceWithInstructions(config, SERVICES.github, false);
|
|
327
|
-
console.log(
|
|
328
|
-
console.log(
|
|
329
|
-
console.log(
|
|
309
|
+
console.log(chalk.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
310
|
+
console.log(chalk.bold.cyan(" STEP 3 of 4: Vercel Token (Recommended)"));
|
|
311
|
+
console.log(chalk.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
330
312
|
await connectServiceWithInstructions(config, SERVICES.vercel, false);
|
|
331
|
-
console.log(
|
|
332
|
-
console.log(
|
|
333
|
-
console.log(
|
|
313
|
+
console.log(chalk.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
314
|
+
console.log(chalk.bold.cyan(" STEP 4 of 4: Supabase Token (Optional)"));
|
|
315
|
+
console.log(chalk.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
334
316
|
await connectServiceWithInstructions(config, SERVICES.supabase, false);
|
|
335
317
|
const connectedServices = CORE_SERVICES.filter((key) => config.getCredentials(key)).map((key) => SERVICES[key].name);
|
|
336
318
|
console.log(boxen(
|
|
337
|
-
|
|
319
|
+
chalk.bold.green("\u2713 Setup Complete!\n\n") + chalk.white("Connected: ") + chalk.cyan(connectedServices.join(", ")) + "\n\n" + chalk.bold.white("What to do next:\n\n") + chalk.cyan("1. ") + chalk.white("Open a terminal and navigate to where you want to build:\n") + chalk.dim(" cd C:\\dev\\my-project\n") + chalk.dim(" (or any folder where you want to create your project)\n\n") + chalk.cyan("2. ") + chalk.white("Run CodeBakers:\n") + chalk.dim(" codebakers\n\n") + chalk.bold.white("Or try these commands directly:\n\n") + chalk.dim(" codebakers website ") + chalk.white("Build a website by describing it\n") + chalk.dim(" codebakers init ") + chalk.white("Create a new project from scratch\n") + chalk.dim(" codebakers help ") + chalk.white("See all available commands"),
|
|
338
320
|
{ padding: 1, borderColor: "green", borderStyle: "round" }
|
|
339
321
|
));
|
|
340
322
|
}
|
|
341
323
|
async function connectServiceWithInstructions(config, service, required) {
|
|
342
|
-
console.log(
|
|
343
|
-
console.log(
|
|
324
|
+
console.log(chalk.white(` ${service.name}`));
|
|
325
|
+
console.log(chalk.dim(` ${service.description}
|
|
344
326
|
`));
|
|
345
327
|
if (!required) {
|
|
346
|
-
console.log(
|
|
328
|
+
console.log(chalk.yellow(` ${service.whyNeeded}
|
|
347
329
|
`));
|
|
348
330
|
}
|
|
349
331
|
const action = await p.select({
|
|
@@ -357,15 +339,15 @@ async function connectServiceWithInstructions(config, service, required) {
|
|
|
357
339
|
});
|
|
358
340
|
if (p.isCancel(action) || action === "skip") {
|
|
359
341
|
if (!required) {
|
|
360
|
-
console.log(
|
|
342
|
+
console.log(chalk.dim(`
|
|
361
343
|
Skipped ${service.name}. You can add it later with: codebakers setup
|
|
362
344
|
`));
|
|
363
345
|
}
|
|
364
346
|
return false;
|
|
365
347
|
}
|
|
366
|
-
console.log(
|
|
348
|
+
console.log(chalk.bold.white("\n Here's what to do:\n"));
|
|
367
349
|
service.steps.forEach((step, i) => {
|
|
368
|
-
console.log(
|
|
350
|
+
console.log(chalk.cyan(` ${i + 1}. `) + chalk.white(step));
|
|
369
351
|
});
|
|
370
352
|
console.log("");
|
|
371
353
|
const openBrowser = await p.confirm({
|
|
@@ -373,28 +355,28 @@ async function connectServiceWithInstructions(config, service, required) {
|
|
|
373
355
|
initialValue: true
|
|
374
356
|
});
|
|
375
357
|
if (openBrowser && !p.isCancel(openBrowser)) {
|
|
376
|
-
console.log(
|
|
358
|
+
console.log(chalk.dim(`
|
|
377
359
|
Opening: ${service.url}
|
|
378
360
|
`));
|
|
379
361
|
await open(service.url);
|
|
380
|
-
console.log(
|
|
362
|
+
console.log(chalk.dim(" Complete the steps above, then paste your key below.\n"));
|
|
381
363
|
}
|
|
382
364
|
const credentials = {};
|
|
383
365
|
for (const field of service.fields) {
|
|
384
366
|
const value = await p.text({
|
|
385
|
-
message: field.label + (field.hint ?
|
|
367
|
+
message: field.label + (field.hint ? chalk.dim(` (${field.hint})`) : "") + ":",
|
|
386
368
|
placeholder: field.placeholder,
|
|
387
369
|
validate: field.validate
|
|
388
370
|
});
|
|
389
371
|
if (p.isCancel(value)) return false;
|
|
390
372
|
if (!value) {
|
|
391
373
|
if (required) {
|
|
392
|
-
console.log(
|
|
374
|
+
console.log(chalk.red(`
|
|
393
375
|
${field.label} is required.
|
|
394
376
|
`));
|
|
395
377
|
return false;
|
|
396
378
|
}
|
|
397
|
-
console.log(
|
|
379
|
+
console.log(chalk.dim(`
|
|
398
380
|
Skipped ${service.name}.
|
|
399
381
|
`));
|
|
400
382
|
return false;
|
|
@@ -402,24 +384,24 @@ async function connectServiceWithInstructions(config, service, required) {
|
|
|
402
384
|
credentials[field.key] = value;
|
|
403
385
|
}
|
|
404
386
|
config.setCredentials(service.key, credentials);
|
|
405
|
-
console.log(
|
|
387
|
+
console.log(chalk.green(`
|
|
406
388
|
\u2713 ${service.name} connected successfully!
|
|
407
389
|
`));
|
|
408
390
|
return true;
|
|
409
391
|
}
|
|
410
392
|
async function showManagementMenu(config) {
|
|
411
|
-
console.log(
|
|
393
|
+
console.log(chalk.bold.cyan("\n CodeBakers Settings\n"));
|
|
412
394
|
const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
|
|
413
395
|
const connected = allServices.filter((key) => config.getCredentials(key));
|
|
414
396
|
const notConnected = allServices.filter((key) => !config.getCredentials(key));
|
|
415
|
-
console.log(
|
|
397
|
+
console.log(chalk.green(" Connected:"));
|
|
416
398
|
connected.forEach((key) => {
|
|
417
|
-
console.log(
|
|
399
|
+
console.log(chalk.green(` \u2713 ${SERVICES[key].name}`));
|
|
418
400
|
});
|
|
419
401
|
if (notConnected.length > 0) {
|
|
420
|
-
console.log(
|
|
402
|
+
console.log(chalk.dim("\n Not connected:"));
|
|
421
403
|
notConnected.forEach((key) => {
|
|
422
|
-
console.log(
|
|
404
|
+
console.log(chalk.dim(` \u25CB ${SERVICES[key].name}`));
|
|
423
405
|
});
|
|
424
406
|
}
|
|
425
407
|
console.log("");
|
|
@@ -451,7 +433,7 @@ async function addService(config) {
|
|
|
451
433
|
const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
|
|
452
434
|
const unconnected = allServices.filter((key) => !config.getCredentials(key));
|
|
453
435
|
if (unconnected.length === 0) {
|
|
454
|
-
console.log(
|
|
436
|
+
console.log(chalk.green("\n All services are already connected!\n"));
|
|
455
437
|
return;
|
|
456
438
|
}
|
|
457
439
|
const selected = await p.select({
|
|
@@ -468,7 +450,7 @@ async function updateService(config) {
|
|
|
468
450
|
const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
|
|
469
451
|
const connected = allServices.filter((key) => config.getCredentials(key));
|
|
470
452
|
if (connected.length === 0) {
|
|
471
|
-
console.log(
|
|
453
|
+
console.log(chalk.yellow("\n No services connected yet.\n"));
|
|
472
454
|
return;
|
|
473
455
|
}
|
|
474
456
|
const selected = await p.select({
|
|
@@ -482,26 +464,26 @@ async function updateService(config) {
|
|
|
482
464
|
await connectServiceWithInstructions(config, SERVICES[selected], false);
|
|
483
465
|
}
|
|
484
466
|
async function resetConfig(config) {
|
|
485
|
-
console.log(
|
|
467
|
+
console.log(chalk.yellow("\n \u26A0\uFE0F This will remove ALL your saved API keys.\n"));
|
|
486
468
|
const confirm13 = await p.confirm({
|
|
487
469
|
message: "Are you sure?",
|
|
488
470
|
initialValue: false
|
|
489
471
|
});
|
|
490
472
|
if (!confirm13 || p.isCancel(confirm13)) {
|
|
491
|
-
console.log(
|
|
473
|
+
console.log(chalk.dim("\n Cancelled.\n"));
|
|
492
474
|
return;
|
|
493
475
|
}
|
|
494
476
|
const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
|
|
495
477
|
for (const key of allServices) {
|
|
496
478
|
config.setCredentials(key, null);
|
|
497
479
|
}
|
|
498
|
-
console.log(
|
|
499
|
-
console.log(
|
|
480
|
+
console.log(chalk.green("\n \u2713 All settings reset.\n"));
|
|
481
|
+
console.log(chalk.dim(" Run `codebakers setup` to configure again.\n"));
|
|
500
482
|
}
|
|
501
483
|
|
|
502
484
|
// src/commands/init.ts
|
|
503
485
|
import * as p2 from "@clack/prompts";
|
|
504
|
-
import
|
|
486
|
+
import chalk2 from "chalk";
|
|
505
487
|
import * as fs from "fs-extra";
|
|
506
488
|
import * as path from "path";
|
|
507
489
|
import { execa as execa3 } from "execa";
|
|
@@ -1002,7 +984,7 @@ async function initCommand(options = {}) {
|
|
|
1002
984
|
p2.log.error("Please run `codebakers setup` first.");
|
|
1003
985
|
return;
|
|
1004
986
|
}
|
|
1005
|
-
p2.intro(
|
|
987
|
+
p2.intro(chalk2.bgCyan.black(" Create New Project "));
|
|
1006
988
|
let projectName = options.name;
|
|
1007
989
|
if (!projectName) {
|
|
1008
990
|
const name = await p2.text({
|
|
@@ -1196,18 +1178,18 @@ Domain: ${domain || "Vercel default"}`,
|
|
|
1196
1178
|
path: projectPath,
|
|
1197
1179
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1198
1180
|
});
|
|
1199
|
-
p2.outro(
|
|
1181
|
+
p2.outro(chalk2.green(`
|
|
1200
1182
|
\u2713 Project created!
|
|
1201
1183
|
|
|
1202
|
-
${
|
|
1203
|
-
${
|
|
1204
|
-
${
|
|
1184
|
+
${chalk2.bold("Your project is ready:")}
|
|
1185
|
+
${chalk2.cyan(`cd ${projectName}`)}
|
|
1186
|
+
${chalk2.cyan("codebakers code")}
|
|
1205
1187
|
|
|
1206
|
-
${
|
|
1207
|
-
${
|
|
1208
|
-
${
|
|
1209
|
-
${
|
|
1210
|
-
${
|
|
1188
|
+
${chalk2.dim("Shortcuts:")}
|
|
1189
|
+
${chalk2.cyan("codebakers")} \u2014 Interactive menu
|
|
1190
|
+
${chalk2.cyan("codebakers code")} \u2014 AI coding agent
|
|
1191
|
+
${chalk2.cyan("codebakers check")} \u2014 Pattern enforcement
|
|
1192
|
+
${chalk2.cyan("codebakers deploy")} \u2014 Deploy to production
|
|
1211
1193
|
`));
|
|
1212
1194
|
} catch (error) {
|
|
1213
1195
|
spinner16.stop("Error occurred");
|
|
@@ -1470,7 +1452,7 @@ echo "\u2713 CodeBakers check passed"
|
|
|
1470
1452
|
|
|
1471
1453
|
// src/commands/code.ts
|
|
1472
1454
|
import * as p6 from "@clack/prompts";
|
|
1473
|
-
import
|
|
1455
|
+
import chalk6 from "chalk";
|
|
1474
1456
|
import * as fs6 from "fs-extra";
|
|
1475
1457
|
import * as path5 from "path";
|
|
1476
1458
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -1778,7 +1760,7 @@ async function loadPatterns(config) {
|
|
|
1778
1760
|
|
|
1779
1761
|
// src/commands/check.ts
|
|
1780
1762
|
import * as p3 from "@clack/prompts";
|
|
1781
|
-
import
|
|
1763
|
+
import chalk3 from "chalk";
|
|
1782
1764
|
import * as fs3 from "fs-extra";
|
|
1783
1765
|
import * as path3 from "path";
|
|
1784
1766
|
import glob from "fast-glob";
|
|
@@ -1935,7 +1917,7 @@ async function checkCommand(options = {}) {
|
|
|
1935
1917
|
p3.log.error("Not in a CodeBakers project.");
|
|
1936
1918
|
return;
|
|
1937
1919
|
}
|
|
1938
|
-
p3.intro(
|
|
1920
|
+
p3.intro(chalk3.bgCyan.black(" CodeBakers Pattern Check "));
|
|
1939
1921
|
const spinner16 = p3.spinner();
|
|
1940
1922
|
spinner16.start("Analyzing code...");
|
|
1941
1923
|
const result = await runPatternCheck(options.fix || false);
|
|
@@ -1951,12 +1933,12 @@ async function checkCommand(options = {}) {
|
|
|
1951
1933
|
}
|
|
1952
1934
|
const errors = result.violations.filter((v) => v.severity === "error");
|
|
1953
1935
|
if (errors.length > 0) {
|
|
1954
|
-
p3.outro(
|
|
1936
|
+
p3.outro(chalk3.red(`\u274C ${errors.length} errors found. Fix before committing.`));
|
|
1955
1937
|
process.exit(1);
|
|
1956
1938
|
} else if (result.violations.length > 0) {
|
|
1957
|
-
p3.outro(
|
|
1939
|
+
p3.outro(chalk3.yellow(`\u26A0\uFE0F ${result.violations.length} warnings. Consider fixing.`));
|
|
1958
1940
|
} else {
|
|
1959
|
-
p3.outro(
|
|
1941
|
+
p3.outro(chalk3.green("\u2713 All patterns satisfied!"));
|
|
1960
1942
|
}
|
|
1961
1943
|
}
|
|
1962
1944
|
async function runPatternCheck(autoFix2) {
|
|
@@ -2012,11 +1994,11 @@ async function runPatternCheck(autoFix2) {
|
|
|
2012
1994
|
};
|
|
2013
1995
|
}
|
|
2014
1996
|
function displayResults(result) {
|
|
2015
|
-
console.log(
|
|
1997
|
+
console.log(chalk3.dim(`
|
|
2016
1998
|
Checked ${result.filesChecked} files
|
|
2017
1999
|
`));
|
|
2018
2000
|
if (result.violations.length === 0) {
|
|
2019
|
-
console.log(
|
|
2001
|
+
console.log(chalk3.green(" \u2713 No violations found\n"));
|
|
2020
2002
|
return;
|
|
2021
2003
|
}
|
|
2022
2004
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -2027,22 +2009,22 @@ Checked ${result.filesChecked} files
|
|
|
2027
2009
|
byFile.get(v.file).push(v);
|
|
2028
2010
|
}
|
|
2029
2011
|
for (const [file, fileViolations] of byFile) {
|
|
2030
|
-
console.log(
|
|
2012
|
+
console.log(chalk3.bold(file));
|
|
2031
2013
|
for (const v of fileViolations) {
|
|
2032
|
-
const icon = v.severity === "error" ?
|
|
2033
|
-
const fixable = v.autoFixable ?
|
|
2014
|
+
const icon = v.severity === "error" ? chalk3.red("\u2717") : chalk3.yellow("\u26A0");
|
|
2015
|
+
const fixable = v.autoFixable ? chalk3.dim(" (auto-fixable)") : "";
|
|
2034
2016
|
console.log(` ${icon} Line ${v.line}: ${v.message}${fixable}`);
|
|
2035
2017
|
}
|
|
2036
2018
|
console.log("");
|
|
2037
2019
|
}
|
|
2038
2020
|
const errors = result.violations.filter((v) => v.severity === "error").length;
|
|
2039
2021
|
const warnings = result.violations.filter((v) => v.severity === "warning").length;
|
|
2040
|
-
console.log(
|
|
2022
|
+
console.log(chalk3.bold("Summary:"));
|
|
2041
2023
|
if (errors > 0) {
|
|
2042
|
-
console.log(
|
|
2024
|
+
console.log(chalk3.red(` ${errors} error(s)`));
|
|
2043
2025
|
}
|
|
2044
2026
|
if (warnings > 0) {
|
|
2045
|
-
console.log(
|
|
2027
|
+
console.log(chalk3.yellow(` ${warnings} warning(s)`));
|
|
2046
2028
|
}
|
|
2047
2029
|
console.log("");
|
|
2048
2030
|
}
|
|
@@ -2076,7 +2058,7 @@ async function autoFix(violations) {
|
|
|
2076
2058
|
|
|
2077
2059
|
// src/utils/voice.ts
|
|
2078
2060
|
import * as p4 from "@clack/prompts";
|
|
2079
|
-
import
|
|
2061
|
+
import chalk4 from "chalk";
|
|
2080
2062
|
import * as fs4 from "fs-extra";
|
|
2081
2063
|
import { execa as execa4 } from "execa";
|
|
2082
2064
|
var voiceAvailable = null;
|
|
@@ -2104,7 +2086,7 @@ async function checkVoiceAvailability() {
|
|
|
2104
2086
|
}
|
|
2105
2087
|
async function textWithVoice(options) {
|
|
2106
2088
|
const hasVoice = await checkVoiceAvailability();
|
|
2107
|
-
const hint = hasVoice ?
|
|
2089
|
+
const hint = hasVoice ? chalk4.dim(' (type "v" for voice)') : "";
|
|
2108
2090
|
const result = await p4.text({
|
|
2109
2091
|
message: options.message + hint,
|
|
2110
2092
|
placeholder: options.placeholder,
|
|
@@ -2120,7 +2102,7 @@ async function textWithVoice(options) {
|
|
|
2120
2102
|
const val = result.toLowerCase().trim();
|
|
2121
2103
|
if (val === "v" || val === "voice") {
|
|
2122
2104
|
if (!hasVoice) {
|
|
2123
|
-
console.log(
|
|
2105
|
+
console.log(chalk4.yellow("Voice input not available on this system."));
|
|
2124
2106
|
return textWithVoice(options);
|
|
2125
2107
|
}
|
|
2126
2108
|
const voiceResult = await getVoiceInput(options.message);
|
|
@@ -2130,7 +2112,7 @@ async function textWithVoice(options) {
|
|
|
2130
2112
|
if (options.validate) {
|
|
2131
2113
|
const error = options.validate(voiceResult);
|
|
2132
2114
|
if (error) {
|
|
2133
|
-
console.log(
|
|
2115
|
+
console.log(chalk4.red(error));
|
|
2134
2116
|
return textWithVoice(options);
|
|
2135
2117
|
}
|
|
2136
2118
|
}
|
|
@@ -2139,9 +2121,9 @@ async function textWithVoice(options) {
|
|
|
2139
2121
|
return result;
|
|
2140
2122
|
}
|
|
2141
2123
|
async function getVoiceInput(prompt) {
|
|
2142
|
-
console.log(
|
|
2124
|
+
console.log(chalk4.cyan(`
|
|
2143
2125
|
\u{1F3A4} ${prompt}`));
|
|
2144
|
-
console.log(
|
|
2126
|
+
console.log(chalk4.dim(" Speak after the beep. Recording stops after silence.\n"));
|
|
2145
2127
|
const ready = await p4.confirm({
|
|
2146
2128
|
message: "Ready to record?",
|
|
2147
2129
|
initialValue: true
|
|
@@ -2163,7 +2145,7 @@ async function getVoiceInput(prompt) {
|
|
|
2163
2145
|
}
|
|
2164
2146
|
spinner16.stop("Recording complete");
|
|
2165
2147
|
if (transcription) {
|
|
2166
|
-
console.log(
|
|
2148
|
+
console.log(chalk4.green(`
|
|
2167
2149
|
\u2713 Heard: "${transcription}"
|
|
2168
2150
|
`));
|
|
2169
2151
|
const confirm13 = await p4.confirm({
|
|
@@ -2190,13 +2172,13 @@ async function getVoiceInput(prompt) {
|
|
|
2190
2172
|
}
|
|
2191
2173
|
}
|
|
2192
2174
|
} else {
|
|
2193
|
-
console.log(
|
|
2175
|
+
console.log(chalk4.yellow("\n No speech detected. Try again or type your response.\n"));
|
|
2194
2176
|
const text17 = await p4.text({ message: "Type instead:" });
|
|
2195
2177
|
return p4.isCancel(text17) ? null : text17;
|
|
2196
2178
|
}
|
|
2197
2179
|
} catch (error) {
|
|
2198
2180
|
spinner16.stop("Recording failed");
|
|
2199
|
-
console.log(
|
|
2181
|
+
console.log(chalk4.yellow("Voice input failed. Please type instead."));
|
|
2200
2182
|
const text17 = await p4.text({ message: prompt });
|
|
2201
2183
|
return p4.isCancel(text17) ? null : text17;
|
|
2202
2184
|
}
|
|
@@ -2345,7 +2327,7 @@ async function transcribeWithWhisper(audioFile) {
|
|
|
2345
2327
|
|
|
2346
2328
|
// src/utils/files.ts
|
|
2347
2329
|
import * as p5 from "@clack/prompts";
|
|
2348
|
-
import
|
|
2330
|
+
import chalk5 from "chalk";
|
|
2349
2331
|
import * as fs5 from "fs-extra";
|
|
2350
2332
|
import * as path4 from "path";
|
|
2351
2333
|
import { execa as execa5 } from "execa";
|
|
@@ -2382,7 +2364,7 @@ async function readFile5(filePath) {
|
|
|
2382
2364
|
}
|
|
2383
2365
|
const stats = await fs5.stat(cleanPath);
|
|
2384
2366
|
if (stats.size > 10 * 1024 * 1024) {
|
|
2385
|
-
console.log(
|
|
2367
|
+
console.log(chalk5.yellow("File too large (max 10MB)"));
|
|
2386
2368
|
return null;
|
|
2387
2369
|
}
|
|
2388
2370
|
const ext = path4.extname(cleanPath).toLowerCase();
|
|
@@ -2472,7 +2454,7 @@ async function readFile5(filePath) {
|
|
|
2472
2454
|
}
|
|
2473
2455
|
}
|
|
2474
2456
|
} catch (error) {
|
|
2475
|
-
console.log(
|
|
2457
|
+
console.log(chalk5.red(`Error reading file: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
2476
2458
|
return null;
|
|
2477
2459
|
}
|
|
2478
2460
|
}
|
|
@@ -2528,9 +2510,9 @@ async function handlePastedContent(text17) {
|
|
|
2528
2510
|
if (!looksLikePaste(text17)) {
|
|
2529
2511
|
return null;
|
|
2530
2512
|
}
|
|
2531
|
-
console.log(
|
|
2513
|
+
console.log(chalk5.cyan("\n\u{1F4CB} Detected pasted content!\n"));
|
|
2532
2514
|
const preview = text17.length > 200 ? text17.slice(0, 200) + "..." : text17;
|
|
2533
|
-
console.log(
|
|
2515
|
+
console.log(chalk5.dim(preview));
|
|
2534
2516
|
console.log("");
|
|
2535
2517
|
const action = await p5.select({
|
|
2536
2518
|
message: "What should I do with this?",
|
|
@@ -2590,11 +2572,11 @@ ${text17}
|
|
|
2590
2572
|
async function codeCommand(prompt, options = {}) {
|
|
2591
2573
|
const config = new Config();
|
|
2592
2574
|
if (!config.isConfigured()) {
|
|
2593
|
-
console.log(
|
|
2575
|
+
console.log(chalk6.yellow(`
|
|
2594
2576
|
\u26A0\uFE0F CodeBakers isn't set up yet.
|
|
2595
2577
|
|
|
2596
2578
|
Run this first:
|
|
2597
|
-
${
|
|
2579
|
+
${chalk6.cyan("codebakers setup")}
|
|
2598
2580
|
|
|
2599
2581
|
This connects your API keys (Anthropic, GitHub, etc.)
|
|
2600
2582
|
so CodeBakers can generate code and deploy for you.
|
|
@@ -2602,28 +2584,28 @@ async function codeCommand(prompt, options = {}) {
|
|
|
2602
2584
|
return;
|
|
2603
2585
|
}
|
|
2604
2586
|
if (!config.isInProject()) {
|
|
2605
|
-
console.log(
|
|
2587
|
+
console.log(chalk6.yellow(`
|
|
2606
2588
|
\u26A0\uFE0F You're not in a CodeBakers project.
|
|
2607
2589
|
|
|
2608
2590
|
Options:
|
|
2609
|
-
${
|
|
2610
|
-
${
|
|
2611
|
-
${
|
|
2591
|
+
${chalk6.cyan("codebakers init")} Create a new project here
|
|
2592
|
+
${chalk6.cyan("codebakers website")} Build a website by describing it
|
|
2593
|
+
${chalk6.cyan("cd my-project")} Navigate to an existing project
|
|
2612
2594
|
`));
|
|
2613
2595
|
return;
|
|
2614
2596
|
}
|
|
2615
2597
|
const anthropicCreds = config.getCredentials("anthropic");
|
|
2616
2598
|
if (!anthropicCreds?.apiKey) {
|
|
2617
|
-
console.log(
|
|
2599
|
+
console.log(chalk6.yellow(`
|
|
2618
2600
|
\u26A0\uFE0F Anthropic API key not configured.
|
|
2619
2601
|
|
|
2620
2602
|
The AI coding agent needs Claude to work.
|
|
2621
2603
|
|
|
2622
2604
|
Run this to add your API key:
|
|
2623
|
-
${
|
|
2605
|
+
${chalk6.cyan("codebakers setup")}
|
|
2624
2606
|
|
|
2625
2607
|
Get an API key at:
|
|
2626
|
-
${
|
|
2608
|
+
${chalk6.dim("https://console.anthropic.com/settings/keys")}
|
|
2627
2609
|
`));
|
|
2628
2610
|
return;
|
|
2629
2611
|
}
|
|
@@ -2633,7 +2615,7 @@ async function codeCommand(prompt, options = {}) {
|
|
|
2633
2615
|
const projectContext = await loadProjectContext();
|
|
2634
2616
|
const patterns = await loadPatterns(config);
|
|
2635
2617
|
const systemPrompt = buildSystemPrompt(projectContext, patterns);
|
|
2636
|
-
console.log(
|
|
2618
|
+
console.log(chalk6.cyan(`
|
|
2637
2619
|
\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E
|
|
2638
2620
|
\u2502 \u{1F916} CodeBakers AI \u2502
|
|
2639
2621
|
\u2502 \u2502
|
|
@@ -2649,13 +2631,13 @@ async function codeCommand(prompt, options = {}) {
|
|
|
2649
2631
|
await processUserInput(prompt, messages, anthropic, systemPrompt, projectContext, config);
|
|
2650
2632
|
}
|
|
2651
2633
|
const hasVoice = await checkVoiceAvailability();
|
|
2652
|
-
console.log(
|
|
2634
|
+
console.log(chalk6.dim(" \u{1F4A1} Tips:"));
|
|
2653
2635
|
if (hasVoice) {
|
|
2654
|
-
console.log(
|
|
2636
|
+
console.log(chalk6.dim(' \u2022 Type "v" for voice input'));
|
|
2655
2637
|
}
|
|
2656
|
-
console.log(
|
|
2657
|
-
console.log(
|
|
2658
|
-
console.log(
|
|
2638
|
+
console.log(chalk6.dim(' \u2022 Type "clip" to read from clipboard'));
|
|
2639
|
+
console.log(chalk6.dim(" \u2022 Drag & drop files or paste file paths"));
|
|
2640
|
+
console.log(chalk6.dim(" \u2022 Paste code directly and I'll detect it\n"));
|
|
2659
2641
|
while (true) {
|
|
2660
2642
|
const input = await textWithVoice({
|
|
2661
2643
|
message: "",
|
|
@@ -2683,14 +2665,14 @@ async function codeCommand(prompt, options = {}) {
|
|
|
2683
2665
|
if (userInput.toLowerCase() === "clip" || userInput.toLowerCase() === "clipboard" || userInput.toLowerCase() === "paste") {
|
|
2684
2666
|
const clipContent = await readClipboard();
|
|
2685
2667
|
if (clipContent) {
|
|
2686
|
-
console.log(
|
|
2668
|
+
console.log(chalk6.green(`
|
|
2687
2669
|
\u{1F4CB} Read ${clipContent.length} characters from clipboard
|
|
2688
2670
|
`));
|
|
2689
2671
|
if (await fs6.pathExists(clipContent.trim())) {
|
|
2690
2672
|
const file = await readFile5(clipContent.trim());
|
|
2691
2673
|
if (file) {
|
|
2692
2674
|
fileContext = formatFilesForContext([file]);
|
|
2693
|
-
console.log(
|
|
2675
|
+
console.log(chalk6.green(`\u{1F4C4} Loaded file: ${file.name}
|
|
2694
2676
|
`));
|
|
2695
2677
|
const instruction = await p6.text({
|
|
2696
2678
|
message: `What should I do with ${file.name}?`,
|
|
@@ -2735,14 +2717,14 @@ ${clipContent}
|
|
|
2735
2717
|
}
|
|
2736
2718
|
}
|
|
2737
2719
|
} else {
|
|
2738
|
-
console.log(
|
|
2720
|
+
console.log(chalk6.yellow("Clipboard is empty"));
|
|
2739
2721
|
continue;
|
|
2740
2722
|
}
|
|
2741
2723
|
} else if (await fs6.pathExists(userInput)) {
|
|
2742
2724
|
const file = await readFile5(userInput);
|
|
2743
2725
|
if (file) {
|
|
2744
2726
|
fileContext = formatFilesForContext([file]);
|
|
2745
|
-
console.log(
|
|
2727
|
+
console.log(chalk6.green(`
|
|
2746
2728
|
\u{1F4C4} Loaded file: ${file.name}
|
|
2747
2729
|
`));
|
|
2748
2730
|
const instruction = await p6.text({
|
|
@@ -2786,9 +2768,9 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
|
|
|
2786
2768
|
messages.push({ role: "assistant", content: assistantMessage });
|
|
2787
2769
|
const actions = parseActions(assistantMessage);
|
|
2788
2770
|
if (actions.length > 0) {
|
|
2789
|
-
console.log(
|
|
2771
|
+
console.log(chalk6.cyan("\n\u{1F4CB} Plan:"));
|
|
2790
2772
|
actions.forEach((action, i) => {
|
|
2791
|
-
console.log(
|
|
2773
|
+
console.log(chalk6.dim(` ${i + 1}. ${action.description}`));
|
|
2792
2774
|
});
|
|
2793
2775
|
console.log("");
|
|
2794
2776
|
const proceed = await p6.confirm({
|
|
@@ -2801,10 +2783,10 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
|
|
|
2801
2783
|
await executeAction(action, spinner16);
|
|
2802
2784
|
}
|
|
2803
2785
|
spinner16.stop("Build complete");
|
|
2804
|
-
console.log(
|
|
2786
|
+
console.log(chalk6.dim("\n\u{1F50D} Running CodeBakers check..."));
|
|
2805
2787
|
const checkResult = await runPatternCheck(false);
|
|
2806
2788
|
if (checkResult.violations.length > 0) {
|
|
2807
|
-
console.log(
|
|
2789
|
+
console.log(chalk6.yellow(`
|
|
2808
2790
|
\u26A0\uFE0F ${checkResult.violations.length} pattern violations found`));
|
|
2809
2791
|
const autoFix2 = await p6.confirm({
|
|
2810
2792
|
message: "Auto-fix violations?",
|
|
@@ -2816,7 +2798,7 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
|
|
|
2816
2798
|
spinner16.stop("Violations fixed");
|
|
2817
2799
|
}
|
|
2818
2800
|
} else {
|
|
2819
|
-
console.log(
|
|
2801
|
+
console.log(chalk6.green("\u2713 All patterns satisfied"));
|
|
2820
2802
|
}
|
|
2821
2803
|
projectContext.recentChanges.push(...actions.map((a) => a.description));
|
|
2822
2804
|
}
|
|
@@ -2825,7 +2807,7 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
|
|
|
2825
2807
|
}
|
|
2826
2808
|
} catch (error) {
|
|
2827
2809
|
spinner16.stop("Error");
|
|
2828
|
-
console.log(
|
|
2810
|
+
console.log(chalk6.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
2829
2811
|
}
|
|
2830
2812
|
}
|
|
2831
2813
|
function buildSystemPrompt(context, patterns) {
|
|
@@ -2996,7 +2978,7 @@ async function checkForWizard(input) {
|
|
|
2996
2978
|
return null;
|
|
2997
2979
|
}
|
|
2998
2980
|
async function runAuthWizard(originalInput) {
|
|
2999
|
-
console.log(
|
|
2981
|
+
console.log(chalk6.cyan("\n\u{1F510} Auth Wizard"));
|
|
3000
2982
|
const authType = await p6.select({
|
|
3001
2983
|
message: "What type of authentication?",
|
|
3002
2984
|
options: [
|
|
@@ -3033,7 +3015,7 @@ async function runAuthWizard(originalInput) {
|
|
|
3033
3015
|
- Follow all CodeBakers patterns`;
|
|
3034
3016
|
}
|
|
3035
3017
|
async function runPaymentWizard(originalInput) {
|
|
3036
|
-
console.log(
|
|
3018
|
+
console.log(chalk6.cyan("\n\u{1F4B3} Payment Wizard"));
|
|
3037
3019
|
const paymentType = await p6.select({
|
|
3038
3020
|
message: "What type of payment flow?",
|
|
3039
3021
|
options: [
|
|
@@ -3063,7 +3045,7 @@ async function runPaymentWizard(originalInput) {
|
|
|
3063
3045
|
- Follow all CodeBakers patterns`;
|
|
3064
3046
|
}
|
|
3065
3047
|
async function runFormWizard(originalInput) {
|
|
3066
|
-
console.log(
|
|
3048
|
+
console.log(chalk6.cyan("\n\u{1F4DD} Form Wizard"));
|
|
3067
3049
|
const formName = await p6.text({
|
|
3068
3050
|
message: "What is this form for?",
|
|
3069
3051
|
placeholder: "Contact form"
|
|
@@ -3079,7 +3061,7 @@ async function runFormWizard(originalInput) {
|
|
|
3079
3061
|
- Follow all CodeBakers patterns`;
|
|
3080
3062
|
}
|
|
3081
3063
|
async function runDashboardWizard(originalInput) {
|
|
3082
|
-
console.log(
|
|
3064
|
+
console.log(chalk6.cyan("\n\u{1F4CA} Dashboard Wizard"));
|
|
3083
3065
|
const components = await p6.multiselect({
|
|
3084
3066
|
message: "What components?",
|
|
3085
3067
|
options: [
|
|
@@ -3101,7 +3083,7 @@ async function runDashboardWizard(originalInput) {
|
|
|
3101
3083
|
- Follow all CodeBakers patterns`;
|
|
3102
3084
|
}
|
|
3103
3085
|
async function runAIWizard(originalInput) {
|
|
3104
|
-
console.log(
|
|
3086
|
+
console.log(chalk6.cyan("\n\u{1F916} AI Feature Wizard"));
|
|
3105
3087
|
const aiType = await p6.select({
|
|
3106
3088
|
message: "What AI feature?",
|
|
3107
3089
|
options: [
|
|
@@ -3128,14 +3110,14 @@ async function handleSlashCommand(command, context, config) {
|
|
|
3128
3110
|
const [cmd, ...args2] = command.slice(1).split(" ");
|
|
3129
3111
|
switch (cmd.toLowerCase()) {
|
|
3130
3112
|
case "deploy":
|
|
3131
|
-
console.log(
|
|
3113
|
+
console.log(chalk6.dim("Running deploy..."));
|
|
3132
3114
|
break;
|
|
3133
3115
|
case "check":
|
|
3134
|
-
console.log(
|
|
3116
|
+
console.log(chalk6.dim("Running pattern check..."));
|
|
3135
3117
|
await runPatternCheck(false);
|
|
3136
3118
|
break;
|
|
3137
3119
|
case "status":
|
|
3138
|
-
console.log(
|
|
3120
|
+
console.log(chalk6.cyan(`
|
|
3139
3121
|
Project: ${context.name}
|
|
3140
3122
|
Framework: ${context.framework}
|
|
3141
3123
|
UI: ${context.ui}
|
|
@@ -3143,17 +3125,17 @@ Files: ${context.existingFiles.length}
|
|
|
3143
3125
|
`));
|
|
3144
3126
|
break;
|
|
3145
3127
|
case "undo":
|
|
3146
|
-
console.log(
|
|
3128
|
+
console.log(chalk6.yellow("Undo not yet implemented"));
|
|
3147
3129
|
break;
|
|
3148
3130
|
case "help":
|
|
3149
3131
|
showHelp();
|
|
3150
3132
|
break;
|
|
3151
3133
|
default:
|
|
3152
|
-
console.log(
|
|
3134
|
+
console.log(chalk6.dim(`Unknown command: ${cmd}`));
|
|
3153
3135
|
}
|
|
3154
3136
|
}
|
|
3155
3137
|
function showHelp() {
|
|
3156
|
-
console.log(
|
|
3138
|
+
console.log(chalk6.cyan(`
|
|
3157
3139
|
Available commands:
|
|
3158
3140
|
|
|
3159
3141
|
/deploy Deploy to production
|
|
@@ -3204,7 +3186,7 @@ Output only the fixed file content, no explanation.`;
|
|
|
3204
3186
|
|
|
3205
3187
|
// src/commands/deploy.ts
|
|
3206
3188
|
import * as p7 from "@clack/prompts";
|
|
3207
|
-
import
|
|
3189
|
+
import chalk7 from "chalk";
|
|
3208
3190
|
import { execa as execa7 } from "execa";
|
|
3209
3191
|
import * as fs7 from "fs-extra";
|
|
3210
3192
|
import * as path6 from "path";
|
|
@@ -3212,33 +3194,33 @@ import Anthropic2 from "@anthropic-ai/sdk";
|
|
|
3212
3194
|
async function deployCommand(options = {}) {
|
|
3213
3195
|
const config = new Config();
|
|
3214
3196
|
if (!config.isInProject()) {
|
|
3215
|
-
console.log(
|
|
3197
|
+
console.log(chalk7.yellow(`
|
|
3216
3198
|
\u26A0\uFE0F You're not in a CodeBakers project.
|
|
3217
3199
|
|
|
3218
3200
|
Navigate to your project first:
|
|
3219
|
-
${
|
|
3201
|
+
${chalk7.cyan("cd my-project")}
|
|
3220
3202
|
|
|
3221
3203
|
Or create a new one:
|
|
3222
|
-
${
|
|
3204
|
+
${chalk7.cyan("codebakers init")}
|
|
3223
3205
|
`));
|
|
3224
3206
|
return;
|
|
3225
3207
|
}
|
|
3226
3208
|
const vercelCreds = config.getCredentials("vercel");
|
|
3227
3209
|
if (!vercelCreds?.token) {
|
|
3228
|
-
console.log(
|
|
3210
|
+
console.log(chalk7.yellow(`
|
|
3229
3211
|
\u26A0\uFE0F Vercel isn't connected.
|
|
3230
3212
|
|
|
3231
3213
|
CodeBakers deploys to Vercel by default.
|
|
3232
3214
|
|
|
3233
3215
|
Run this to connect:
|
|
3234
|
-
${
|
|
3216
|
+
${chalk7.cyan("codebakers setup")}
|
|
3235
3217
|
|
|
3236
3218
|
Or deploy manually:
|
|
3237
|
-
${
|
|
3219
|
+
${chalk7.cyan("npx vercel")}
|
|
3238
3220
|
`));
|
|
3239
3221
|
return;
|
|
3240
3222
|
}
|
|
3241
|
-
p7.intro(
|
|
3223
|
+
p7.intro(chalk7.bgCyan.black(" Deploy to Production "));
|
|
3242
3224
|
const spinner16 = p7.spinner();
|
|
3243
3225
|
if (options.check !== false) {
|
|
3244
3226
|
spinner16.start("Running CodeBakers check...");
|
|
@@ -3254,7 +3236,7 @@ async function deployCommand(options = {}) {
|
|
|
3254
3236
|
});
|
|
3255
3237
|
if (showViolations && !p7.isCancel(showViolations)) {
|
|
3256
3238
|
for (const v of errors) {
|
|
3257
|
-
console.log(
|
|
3239
|
+
console.log(chalk7.red(` \u2717 ${v.file}:${v.line} - ${v.message}`));
|
|
3258
3240
|
}
|
|
3259
3241
|
}
|
|
3260
3242
|
const autoFix2 = await p7.confirm({
|
|
@@ -3262,7 +3244,7 @@ async function deployCommand(options = {}) {
|
|
|
3262
3244
|
initialValue: true
|
|
3263
3245
|
});
|
|
3264
3246
|
if (!autoFix2 || p7.isCancel(autoFix2)) {
|
|
3265
|
-
p7.outro(
|
|
3247
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3266
3248
|
return;
|
|
3267
3249
|
}
|
|
3268
3250
|
spinner16.start("Auto-fixing with AI...");
|
|
@@ -3271,7 +3253,7 @@ async function deployCommand(options = {}) {
|
|
|
3271
3253
|
const recheck = await runPatternCheck(false);
|
|
3272
3254
|
if (!recheck.passed) {
|
|
3273
3255
|
p7.log.error("Some violations remain. Manual fix required.");
|
|
3274
|
-
p7.outro(
|
|
3256
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3275
3257
|
return;
|
|
3276
3258
|
}
|
|
3277
3259
|
}
|
|
@@ -3294,11 +3276,11 @@ async function deployCommand(options = {}) {
|
|
|
3294
3276
|
const fixed = await fixTypeScriptErrors(config);
|
|
3295
3277
|
spinner16.stop(fixed ? "TypeScript errors fixed" : "Could not auto-fix all errors");
|
|
3296
3278
|
if (!fixed) {
|
|
3297
|
-
p7.outro(
|
|
3279
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3298
3280
|
return;
|
|
3299
3281
|
}
|
|
3300
3282
|
} else {
|
|
3301
|
-
p7.outro(
|
|
3283
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3302
3284
|
return;
|
|
3303
3285
|
}
|
|
3304
3286
|
}
|
|
@@ -3318,7 +3300,7 @@ async function deployCommand(options = {}) {
|
|
|
3318
3300
|
spinner16.stop("");
|
|
3319
3301
|
p7.log.error("Build failed.");
|
|
3320
3302
|
const errorOutput = error instanceof Error ? error.message : "Unknown error";
|
|
3321
|
-
console.log(
|
|
3303
|
+
console.log(chalk7.dim(errorOutput));
|
|
3322
3304
|
const fix = await p7.confirm({
|
|
3323
3305
|
message: "Attempt to fix build errors with AI?",
|
|
3324
3306
|
initialValue: true
|
|
@@ -3334,15 +3316,15 @@ async function deployCommand(options = {}) {
|
|
|
3334
3316
|
spinner16.stop("Build successful");
|
|
3335
3317
|
} catch {
|
|
3336
3318
|
spinner16.stop("Build still failing");
|
|
3337
|
-
p7.outro(
|
|
3319
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3338
3320
|
return;
|
|
3339
3321
|
}
|
|
3340
3322
|
} else {
|
|
3341
|
-
p7.outro(
|
|
3323
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3342
3324
|
return;
|
|
3343
3325
|
}
|
|
3344
3326
|
} else {
|
|
3345
|
-
p7.outro(
|
|
3327
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3346
3328
|
return;
|
|
3347
3329
|
}
|
|
3348
3330
|
}
|
|
@@ -3378,14 +3360,14 @@ async function deployCommand(options = {}) {
|
|
|
3378
3360
|
const deployment = await vercel.deploy(process.cwd(), !options.preview);
|
|
3379
3361
|
spinner16.stop("Deployment complete!");
|
|
3380
3362
|
console.log(boxedOutput(`
|
|
3381
|
-
${
|
|
3363
|
+
${chalk7.green("\u2713")} Deployed successfully!
|
|
3382
3364
|
|
|
3383
|
-
${
|
|
3384
|
-
${
|
|
3385
|
-
${
|
|
3365
|
+
${chalk7.bold("URL:")} ${deployment.url}
|
|
3366
|
+
${chalk7.bold("Type:")} ${deployType}
|
|
3367
|
+
${chalk7.bold("Time:")} ${(/* @__PURE__ */ new Date()).toLocaleTimeString()}
|
|
3386
3368
|
|
|
3387
|
-
${
|
|
3388
|
-
${
|
|
3369
|
+
${chalk7.dim("View in Vercel Dashboard:")}
|
|
3370
|
+
${chalk7.dim(deployment.dashboardUrl || "https://vercel.com/dashboard")}
|
|
3389
3371
|
`));
|
|
3390
3372
|
} catch (error) {
|
|
3391
3373
|
spinner16.stop("");
|
|
@@ -3401,7 +3383,7 @@ ${chalk8.dim(deployment.dashboardUrl || "https://vercel.com/dashboard")}
|
|
|
3401
3383
|
spinner16.stop("Fix attempted");
|
|
3402
3384
|
}
|
|
3403
3385
|
}
|
|
3404
|
-
p7.outro(
|
|
3386
|
+
p7.outro(chalk7.red("Deploy failed."));
|
|
3405
3387
|
}
|
|
3406
3388
|
}
|
|
3407
3389
|
async function autoFixWithAI(config, violations) {
|
|
@@ -3559,25 +3541,25 @@ async function connectCommand(service) {
|
|
|
3559
3541
|
|
|
3560
3542
|
// src/commands/status.ts
|
|
3561
3543
|
import * as p8 from "@clack/prompts";
|
|
3562
|
-
import
|
|
3544
|
+
import chalk8 from "chalk";
|
|
3563
3545
|
import * as fs8 from "fs-extra";
|
|
3564
3546
|
import * as path7 from "path";
|
|
3565
3547
|
async function statusCommand() {
|
|
3566
3548
|
const config = new Config();
|
|
3567
3549
|
const cwd = process.cwd();
|
|
3568
|
-
p8.intro(
|
|
3550
|
+
p8.intro(chalk8.bgCyan.black(" Project Status "));
|
|
3569
3551
|
if (!config.isInProject()) {
|
|
3570
3552
|
const projects = config.getProjects();
|
|
3571
3553
|
if (projects.length === 0) {
|
|
3572
3554
|
p8.log.info("No projects found. Run `codebakers init` to create one.");
|
|
3573
3555
|
return;
|
|
3574
3556
|
}
|
|
3575
|
-
console.log(
|
|
3557
|
+
console.log(chalk8.bold("\nYour Projects:\n"));
|
|
3576
3558
|
for (const project of projects) {
|
|
3577
3559
|
const exists = await fs8.pathExists(project.path);
|
|
3578
|
-
const status = exists ?
|
|
3560
|
+
const status = exists ? chalk8.green("\u2713") : chalk8.red("\u2717");
|
|
3579
3561
|
console.log(` ${status} ${project.name}`);
|
|
3580
|
-
console.log(
|
|
3562
|
+
console.log(chalk8.dim(` ${project.path}`));
|
|
3581
3563
|
console.log("");
|
|
3582
3564
|
}
|
|
3583
3565
|
return;
|
|
@@ -3589,24 +3571,24 @@ async function statusCommand() {
|
|
|
3589
3571
|
path7.join(cwd, "package.json")
|
|
3590
3572
|
).catch(() => ({}));
|
|
3591
3573
|
console.log(`
|
|
3592
|
-
${
|
|
3593
|
-
${
|
|
3594
|
-
${
|
|
3595
|
-
|
|
3596
|
-
${
|
|
3597
|
-
${
|
|
3598
|
-
${
|
|
3599
|
-
${
|
|
3574
|
+
${chalk8.bold("Project:")} ${packageJson.name || path7.basename(cwd)}
|
|
3575
|
+
${chalk8.bold("Framework:")} ${projectConfig.framework || "unknown"}
|
|
3576
|
+
${chalk8.bold("UI:")} ${projectConfig.ui || "unknown"}
|
|
3577
|
+
|
|
3578
|
+
${chalk8.bold("Quick Actions:")}
|
|
3579
|
+
${chalk8.cyan("codebakers code")} \u2014 AI coding agent
|
|
3580
|
+
${chalk8.cyan("codebakers check")} \u2014 Pattern enforcement
|
|
3581
|
+
${chalk8.cyan("codebakers deploy")} \u2014 Deploy to production
|
|
3600
3582
|
`);
|
|
3601
3583
|
p8.outro("");
|
|
3602
3584
|
}
|
|
3603
3585
|
|
|
3604
3586
|
// src/commands/gateway.ts
|
|
3605
3587
|
import * as p9 from "@clack/prompts";
|
|
3606
|
-
import
|
|
3588
|
+
import chalk9 from "chalk";
|
|
3607
3589
|
async function gatewayCommand(options = {}) {
|
|
3608
3590
|
const config = new Config();
|
|
3609
|
-
p9.intro(
|
|
3591
|
+
p9.intro(chalk9.bgCyan.black(" Channel Gateway "));
|
|
3610
3592
|
if (options.start) {
|
|
3611
3593
|
await startAllChannels(config);
|
|
3612
3594
|
return;
|
|
@@ -3653,19 +3635,19 @@ async function gatewayCommand(options = {}) {
|
|
|
3653
3635
|
}
|
|
3654
3636
|
async function showGatewayStatus(config) {
|
|
3655
3637
|
const channels = await getChannelStatuses(config);
|
|
3656
|
-
console.log(
|
|
3638
|
+
console.log(chalk9.bold("\n\u{1F4F1} Channel Gateway Status\n"));
|
|
3657
3639
|
for (const channel of channels) {
|
|
3658
3640
|
const statusIcon = {
|
|
3659
|
-
running:
|
|
3660
|
-
stopped:
|
|
3661
|
-
error:
|
|
3662
|
-
connecting:
|
|
3641
|
+
running: chalk9.green("\u25CF"),
|
|
3642
|
+
stopped: chalk9.gray("\u25CB"),
|
|
3643
|
+
error: chalk9.red("\u2717"),
|
|
3644
|
+
connecting: chalk9.yellow("\u25D0")
|
|
3663
3645
|
}[channel.status];
|
|
3664
3646
|
const statusText = {
|
|
3665
|
-
running:
|
|
3666
|
-
stopped:
|
|
3667
|
-
error:
|
|
3668
|
-
connecting:
|
|
3647
|
+
running: chalk9.green("Running"),
|
|
3648
|
+
stopped: chalk9.gray("Stopped"),
|
|
3649
|
+
error: chalk9.red("Error"),
|
|
3650
|
+
connecting: chalk9.yellow("Connecting...")
|
|
3669
3651
|
}[channel.status];
|
|
3670
3652
|
console.log(` ${channel.icon} ${channel.name.padEnd(15)} ${statusIcon} ${statusText}`);
|
|
3671
3653
|
}
|
|
@@ -3751,8 +3733,8 @@ async function connectChannelWizard(config) {
|
|
|
3751
3733
|
}
|
|
3752
3734
|
}
|
|
3753
3735
|
async function connectWhatsApp(config) {
|
|
3754
|
-
p9.log.info(
|
|
3755
|
-
p9.log.info(
|
|
3736
|
+
p9.log.info(chalk9.bold("WhatsApp Setup"));
|
|
3737
|
+
p9.log.info(chalk9.dim(`
|
|
3756
3738
|
WhatsApp uses QR code authentication via Baileys library.
|
|
3757
3739
|
Your phone needs to scan a QR code to connect.
|
|
3758
3740
|
|
|
@@ -3768,7 +3750,7 @@ you'll need a Meta Business account.
|
|
|
3768
3750
|
spinner16.start("Generating QR code...");
|
|
3769
3751
|
try {
|
|
3770
3752
|
spinner16.stop("");
|
|
3771
|
-
console.log(
|
|
3753
|
+
console.log(chalk9.cyan(`
|
|
3772
3754
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
3773
3755
|
\u2551 \u2551
|
|
3774
3756
|
\u2551 \u2584\u2584\u2584\u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584\u2584\u2584 \u2551
|
|
@@ -3804,8 +3786,8 @@ Scan this QR code with WhatsApp:
|
|
|
3804
3786
|
}
|
|
3805
3787
|
}
|
|
3806
3788
|
async function connectTelegram(config) {
|
|
3807
|
-
p9.log.info(
|
|
3808
|
-
p9.log.info(
|
|
3789
|
+
p9.log.info(chalk9.bold("Telegram Bot Setup"));
|
|
3790
|
+
p9.log.info(chalk9.dim(`
|
|
3809
3791
|
To create a Telegram bot:
|
|
3810
3792
|
1. Open Telegram and search for @BotFather
|
|
3811
3793
|
2. Send /newbot
|
|
@@ -3851,8 +3833,8 @@ To create a Telegram bot:
|
|
|
3851
3833
|
}
|
|
3852
3834
|
}
|
|
3853
3835
|
async function connectDiscord(config) {
|
|
3854
|
-
p9.log.info(
|
|
3855
|
-
p9.log.info(
|
|
3836
|
+
p9.log.info(chalk9.bold("Discord Bot Setup"));
|
|
3837
|
+
p9.log.info(chalk9.dim(`
|
|
3856
3838
|
To create a Discord bot:
|
|
3857
3839
|
1. Go to Discord Developer Portal
|
|
3858
3840
|
2. Create a new application
|
|
@@ -3888,8 +3870,8 @@ To create a Discord bot:
|
|
|
3888
3870
|
p9.log.info(`Add bot to server: ${inviteUrl}`);
|
|
3889
3871
|
}
|
|
3890
3872
|
async function connectSlack(config) {
|
|
3891
|
-
p9.log.info(
|
|
3892
|
-
p9.log.info(
|
|
3873
|
+
p9.log.info(chalk9.bold("Slack App Setup"));
|
|
3874
|
+
p9.log.info(chalk9.dim(`
|
|
3893
3875
|
To create a Slack app:
|
|
3894
3876
|
1. Go to Slack API portal
|
|
3895
3877
|
2. Create a new app
|
|
@@ -3922,7 +3904,7 @@ To create a Slack app:
|
|
|
3922
3904
|
p9.log.success("Slack app configured!");
|
|
3923
3905
|
}
|
|
3924
3906
|
async function connectSMS(config) {
|
|
3925
|
-
p9.log.info(
|
|
3907
|
+
p9.log.info(chalk9.bold("SMS via Twilio"));
|
|
3926
3908
|
const twilioConfig = config.getCredentials("twilio");
|
|
3927
3909
|
if (twilioConfig?.accountSid) {
|
|
3928
3910
|
p9.log.info("Twilio is already configured.");
|
|
@@ -3969,7 +3951,7 @@ async function connectSMS(config) {
|
|
|
3969
3951
|
}
|
|
3970
3952
|
async function connectiMessage(config) {
|
|
3971
3953
|
p9.log.warn("iMessage support requires macOS and additional setup.");
|
|
3972
|
-
p9.log.info(
|
|
3954
|
+
p9.log.info(chalk9.dim(`
|
|
3973
3955
|
iMessage integration uses AppleScript on macOS.
|
|
3974
3956
|
This requires:
|
|
3975
3957
|
1. macOS with Messages app
|
|
@@ -3988,7 +3970,7 @@ async function startAllChannels(config) {
|
|
|
3988
3970
|
spinner16.start("Starting channel gateway...");
|
|
3989
3971
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3990
3972
|
spinner16.stop("Gateway started");
|
|
3991
|
-
console.log(
|
|
3973
|
+
console.log(chalk9.green(`
|
|
3992
3974
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
3993
3975
|
\u2551 Gateway is running! \u2551
|
|
3994
3976
|
\u2551 \u2551
|
|
@@ -4007,7 +3989,7 @@ async function stopAllChannels(config) {
|
|
|
4007
3989
|
spinner16.stop("Gateway stopped");
|
|
4008
3990
|
}
|
|
4009
3991
|
async function deployGatewayWizard(config) {
|
|
4010
|
-
p9.log.info(
|
|
3992
|
+
p9.log.info(chalk9.bold("Deploy Gateway to Cloud"));
|
|
4011
3993
|
const platform = await p9.select({
|
|
4012
3994
|
message: "Where do you want to deploy?",
|
|
4013
3995
|
options: [
|
|
@@ -4020,14 +4002,14 @@ async function deployGatewayWizard(config) {
|
|
|
4020
4002
|
switch (platform) {
|
|
4021
4003
|
case "codebakers":
|
|
4022
4004
|
p9.log.info("CodeBakers Cloud coming soon!");
|
|
4023
|
-
p9.log.info(
|
|
4005
|
+
p9.log.info(chalk9.dim("Sign up at https://codebakers.dev/cloud"));
|
|
4024
4006
|
break;
|
|
4025
4007
|
case "vps":
|
|
4026
4008
|
await deployToVPS(config);
|
|
4027
4009
|
break;
|
|
4028
4010
|
case "local":
|
|
4029
4011
|
p9.log.info("Local deployment guide:");
|
|
4030
|
-
p9.log.info(
|
|
4012
|
+
p9.log.info(chalk9.dim(`
|
|
4031
4013
|
1. Install Node.js on your server
|
|
4032
4014
|
2. Clone your project
|
|
4033
4015
|
3. Run: npm install
|
|
@@ -4051,7 +4033,7 @@ async function deployToVPS(config) {
|
|
|
4051
4033
|
if (p9.isCancel(provider)) return;
|
|
4052
4034
|
if (provider === "digitalocean") {
|
|
4053
4035
|
p9.log.info("DigitalOcean auto-deploy:");
|
|
4054
|
-
p9.log.info(
|
|
4036
|
+
p9.log.info(chalk9.dim(`
|
|
4055
4037
|
1. Opening DigitalOcean login...
|
|
4056
4038
|
2. We'll create a $6/mo droplet
|
|
4057
4039
|
3. Install CodeBakers gateway
|
|
@@ -4066,7 +4048,7 @@ async function deployToVPS(config) {
|
|
|
4066
4048
|
await open3("https://cloud.digitalocean.com/");
|
|
4067
4049
|
}
|
|
4068
4050
|
} else {
|
|
4069
|
-
p9.log.info(
|
|
4051
|
+
p9.log.info(chalk9.dim(`
|
|
4070
4052
|
Manual VPS setup:
|
|
4071
4053
|
|
|
4072
4054
|
1. Create a VPS (Ubuntu 22.04 recommended)
|
|
@@ -4083,57 +4065,57 @@ Manual VPS setup:
|
|
|
4083
4065
|
|
|
4084
4066
|
// src/commands/learn.ts
|
|
4085
4067
|
import * as p10 from "@clack/prompts";
|
|
4086
|
-
import
|
|
4068
|
+
import chalk10 from "chalk";
|
|
4087
4069
|
async function learnCommand() {
|
|
4088
4070
|
const config = new Config();
|
|
4089
4071
|
const learning = config.getLearning();
|
|
4090
|
-
p10.intro(
|
|
4091
|
-
console.log(
|
|
4072
|
+
p10.intro(chalk10.bgCyan.black(" Learning Settings "));
|
|
4073
|
+
console.log(chalk10.bold("\n\u{1F9E0} What CodeBakers has learned about you:\n"));
|
|
4092
4074
|
const shortcuts = Object.entries(learning.shortcuts);
|
|
4093
4075
|
if (shortcuts.length > 0) {
|
|
4094
|
-
console.log(
|
|
4076
|
+
console.log(chalk10.bold("Shortcuts:"));
|
|
4095
4077
|
for (const [short, full] of shortcuts) {
|
|
4096
|
-
console.log(` ${
|
|
4078
|
+
console.log(` ${chalk10.cyan(short)} \u2192 ${full}`);
|
|
4097
4079
|
}
|
|
4098
4080
|
console.log("");
|
|
4099
4081
|
}
|
|
4100
4082
|
const prefs = Object.entries(learning.preferences);
|
|
4101
4083
|
if (prefs.length > 0) {
|
|
4102
|
-
console.log(
|
|
4084
|
+
console.log(chalk10.bold("Preferences:"));
|
|
4103
4085
|
for (const [key, value] of prefs) {
|
|
4104
|
-
console.log(` ${key}: ${
|
|
4086
|
+
console.log(` ${key}: ${chalk10.cyan(String(value))}`);
|
|
4105
4087
|
}
|
|
4106
4088
|
console.log("");
|
|
4107
4089
|
}
|
|
4108
4090
|
if (shortcuts.length === 0 && prefs.length === 0) {
|
|
4109
|
-
console.log(
|
|
4091
|
+
console.log(chalk10.dim(" Nothing learned yet. Use CodeBakers more!\n"));
|
|
4110
4092
|
}
|
|
4111
4093
|
p10.outro("");
|
|
4112
4094
|
}
|
|
4113
4095
|
|
|
4114
4096
|
// src/commands/security.ts
|
|
4115
4097
|
import * as p11 from "@clack/prompts";
|
|
4116
|
-
import
|
|
4098
|
+
import chalk11 from "chalk";
|
|
4117
4099
|
import * as fs9 from "fs-extra";
|
|
4118
4100
|
import glob2 from "fast-glob";
|
|
4119
4101
|
import * as path8 from "path";
|
|
4120
4102
|
async function securityCommand() {
|
|
4121
|
-
p11.intro(
|
|
4103
|
+
p11.intro(chalk11.bgCyan.black(" Security Audit "));
|
|
4122
4104
|
const spinner16 = p11.spinner();
|
|
4123
4105
|
spinner16.start("Scanning for security issues...");
|
|
4124
4106
|
const issues = await runSecurityScan();
|
|
4125
4107
|
spinner16.stop("Scan complete");
|
|
4126
4108
|
if (issues.length === 0) {
|
|
4127
|
-
console.log(
|
|
4109
|
+
console.log(chalk11.green("\n\u2713 No security issues found!\n"));
|
|
4128
4110
|
displaySecurityScore(100);
|
|
4129
4111
|
} else {
|
|
4130
|
-
console.log(
|
|
4112
|
+
console.log(chalk11.yellow(`
|
|
4131
4113
|
\u26A0\uFE0F ${issues.length} security issues found:
|
|
4132
4114
|
`));
|
|
4133
4115
|
for (const issue of issues) {
|
|
4134
|
-
const icon = issue.severity === "critical" ?
|
|
4135
|
-
console.log(`${icon} ${
|
|
4136
|
-
console.log(
|
|
4116
|
+
const icon = issue.severity === "critical" ? chalk11.red("\u{1F534}") : issue.severity === "high" ? chalk11.red("\u{1F7E0}") : chalk11.yellow("\u{1F7E1}");
|
|
4117
|
+
console.log(`${icon} ${chalk11.bold(issue.title)}`);
|
|
4118
|
+
console.log(chalk11.dim(` ${issue.file}:${issue.line}`));
|
|
4137
4119
|
console.log(` ${issue.description}
|
|
4138
4120
|
`);
|
|
4139
4121
|
}
|
|
@@ -4183,9 +4165,9 @@ async function runSecurityScan() {
|
|
|
4183
4165
|
return issues;
|
|
4184
4166
|
}
|
|
4185
4167
|
function displaySecurityScore(score) {
|
|
4186
|
-
const color = score >= 80 ?
|
|
4168
|
+
const color = score >= 80 ? chalk11.green : score >= 50 ? chalk11.yellow : chalk11.red;
|
|
4187
4169
|
const grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";
|
|
4188
|
-
console.log(
|
|
4170
|
+
console.log(chalk11.bold("Security Score:"));
|
|
4189
4171
|
console.log(color(`
|
|
4190
4172
|
${score}/100 Grade: ${grade}
|
|
4191
4173
|
`));
|
|
@@ -4193,11 +4175,11 @@ function displaySecurityScore(score) {
|
|
|
4193
4175
|
|
|
4194
4176
|
// src/commands/generate.ts
|
|
4195
4177
|
import * as p12 from "@clack/prompts";
|
|
4196
|
-
import
|
|
4178
|
+
import chalk12 from "chalk";
|
|
4197
4179
|
import * as fs10 from "fs-extra";
|
|
4198
4180
|
import * as path9 from "path";
|
|
4199
4181
|
async function generateCommand(type) {
|
|
4200
|
-
p12.intro(
|
|
4182
|
+
p12.intro(chalk12.bgCyan.black(" Generate "));
|
|
4201
4183
|
const generateType = type || await p12.select({
|
|
4202
4184
|
message: "What do you want to generate?",
|
|
4203
4185
|
options: [
|
|
@@ -4361,9 +4343,9 @@ export function ${name}Form({ onSuccess }: { onSuccess?: () => void }) {
|
|
|
4361
4343
|
|
|
4362
4344
|
// src/commands/fix.ts
|
|
4363
4345
|
import * as p13 from "@clack/prompts";
|
|
4364
|
-
import
|
|
4346
|
+
import chalk13 from "chalk";
|
|
4365
4347
|
async function fixCommand() {
|
|
4366
|
-
p13.intro(
|
|
4348
|
+
p13.intro(chalk13.bgCyan.black(" Auto-Fix "));
|
|
4367
4349
|
const spinner16 = p13.spinner();
|
|
4368
4350
|
spinner16.start("Analyzing code...");
|
|
4369
4351
|
const result = await runPatternCheck(true);
|
|
@@ -4372,12 +4354,12 @@ async function fixCommand() {
|
|
|
4372
4354
|
} else {
|
|
4373
4355
|
spinner16.stop(`Fixed ${result.violations.length} issues`);
|
|
4374
4356
|
}
|
|
4375
|
-
p13.outro(
|
|
4357
|
+
p13.outro(chalk13.green("Done!"));
|
|
4376
4358
|
}
|
|
4377
4359
|
|
|
4378
4360
|
// src/commands/design.ts
|
|
4379
4361
|
import * as p14 from "@clack/prompts";
|
|
4380
|
-
import
|
|
4362
|
+
import chalk14 from "chalk";
|
|
4381
4363
|
import * as fs11 from "fs-extra";
|
|
4382
4364
|
import * as path10 from "path";
|
|
4383
4365
|
var DESIGN_PROFILES = {
|
|
@@ -4436,7 +4418,7 @@ async function designCommand(subcommand) {
|
|
|
4436
4418
|
p14.log.error("Not in a CodeBakers project. Run `codebakers init` first.");
|
|
4437
4419
|
return;
|
|
4438
4420
|
}
|
|
4439
|
-
p14.intro(
|
|
4421
|
+
p14.intro(chalk14.bgCyan.black(" Design System "));
|
|
4440
4422
|
const action = subcommand || await p14.select({
|
|
4441
4423
|
message: "What do you want to do?",
|
|
4442
4424
|
options: [
|
|
@@ -4481,7 +4463,7 @@ async function setProfile() {
|
|
|
4481
4463
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4482
4464
|
}, { spaces: 2 });
|
|
4483
4465
|
p14.log.success(`Design profile set to ${selected.name}`);
|
|
4484
|
-
console.log(
|
|
4466
|
+
console.log(chalk14.dim(`
|
|
4485
4467
|
Fonts: ${selected.fonts.heading} / ${selected.fonts.body}
|
|
4486
4468
|
Corners: ${selected.corners}
|
|
4487
4469
|
Shadows: ${selected.shadows}
|
|
@@ -4511,10 +4493,10 @@ async function generatePalette() {
|
|
|
4511
4493
|
}, { spaces: 2 });
|
|
4512
4494
|
p14.log.success("Color palette generated!");
|
|
4513
4495
|
console.log(`
|
|
4514
|
-
${
|
|
4515
|
-
${
|
|
4516
|
-
${
|
|
4517
|
-
${
|
|
4496
|
+
${chalk14.bgHex(palette.brand[500]).black(" Brand ")} ${palette.brand[500]}
|
|
4497
|
+
${chalk14.bgHex(palette.brand[100]).black(" Light ")} ${palette.brand[100]}
|
|
4498
|
+
${chalk14.bgHex(palette.brand[900]).white(" Dark ")} ${palette.brand[900]}
|
|
4499
|
+
${chalk14.bgHex(palette.accent).black(" Accent ")} ${palette.accent}
|
|
4518
4500
|
`);
|
|
4519
4501
|
}
|
|
4520
4502
|
function generateColorPalette(hex) {
|
|
@@ -4600,13 +4582,13 @@ async function checkDesign() {
|
|
|
4600
4582
|
}
|
|
4601
4583
|
spinner16.stop("Check complete");
|
|
4602
4584
|
if (issues.length === 0) {
|
|
4603
|
-
console.log(
|
|
4585
|
+
console.log(chalk14.green("\n\u2713 No design issues found!\n"));
|
|
4604
4586
|
} else {
|
|
4605
|
-
console.log(
|
|
4587
|
+
console.log(chalk14.yellow(`
|
|
4606
4588
|
\u26A0\uFE0F ${issues.length} design issues found:
|
|
4607
4589
|
`));
|
|
4608
4590
|
for (const issue of issues) {
|
|
4609
|
-
console.log(
|
|
4591
|
+
console.log(chalk14.dim(` \u2022 ${issue}`));
|
|
4610
4592
|
}
|
|
4611
4593
|
console.log("");
|
|
4612
4594
|
}
|
|
@@ -4618,7 +4600,7 @@ async function viewSettings() {
|
|
|
4618
4600
|
return;
|
|
4619
4601
|
}
|
|
4620
4602
|
const config = await fs11.readJson(configPath);
|
|
4621
|
-
console.log(
|
|
4603
|
+
console.log(chalk14.bold("\nCurrent Design Settings:\n"));
|
|
4622
4604
|
console.log(` Profile: ${config.name || config.profile}`);
|
|
4623
4605
|
console.log(` Fonts: ${config.fonts?.heading} / ${config.fonts?.body}`);
|
|
4624
4606
|
console.log(` Corners: ${config.corners}`);
|
|
@@ -4633,7 +4615,7 @@ async function viewSettings() {
|
|
|
4633
4615
|
|
|
4634
4616
|
// src/commands/migrate.ts
|
|
4635
4617
|
import * as p15 from "@clack/prompts";
|
|
4636
|
-
import
|
|
4618
|
+
import chalk15 from "chalk";
|
|
4637
4619
|
import { execa as execa8 } from "execa";
|
|
4638
4620
|
import * as fs12 from "fs-extra";
|
|
4639
4621
|
import * as path11 from "path";
|
|
@@ -4643,7 +4625,7 @@ async function migrateCommand(options = {}) {
|
|
|
4643
4625
|
p15.log.error("Not in a CodeBakers project.");
|
|
4644
4626
|
return;
|
|
4645
4627
|
}
|
|
4646
|
-
p15.intro(
|
|
4628
|
+
p15.intro(chalk15.bgCyan.black(" Database Migrations "));
|
|
4647
4629
|
const migrationTool = await detectMigrationTool();
|
|
4648
4630
|
if (!migrationTool) {
|
|
4649
4631
|
p15.log.error("No migration tool detected. Supported: Drizzle, Prisma, Supabase CLI");
|
|
@@ -4713,10 +4695,10 @@ async function checkMigrationStatus(tool) {
|
|
|
4713
4695
|
}
|
|
4714
4696
|
spinner16.stop("Status check complete");
|
|
4715
4697
|
if (result?.stdout) {
|
|
4716
|
-
console.log(
|
|
4698
|
+
console.log(chalk15.dim(result.stdout));
|
|
4717
4699
|
}
|
|
4718
4700
|
if (result?.stderr) {
|
|
4719
|
-
console.log(
|
|
4701
|
+
console.log(chalk15.yellow(result.stderr));
|
|
4720
4702
|
}
|
|
4721
4703
|
} catch (error) {
|
|
4722
4704
|
spinner16.stop("Error checking status");
|
|
@@ -4747,7 +4729,7 @@ async function generateMigration(tool) {
|
|
|
4747
4729
|
}
|
|
4748
4730
|
spinner16.stop("Migration generated");
|
|
4749
4731
|
if (result?.stdout) {
|
|
4750
|
-
console.log(
|
|
4732
|
+
console.log(chalk15.dim(result.stdout));
|
|
4751
4733
|
}
|
|
4752
4734
|
} catch (error) {
|
|
4753
4735
|
spinner16.stop("Error generating migration");
|
|
@@ -4784,13 +4766,13 @@ async function pushMigration(tool) {
|
|
|
4784
4766
|
if (result?.exitCode !== 0) {
|
|
4785
4767
|
spinner16.stop("Migration push failed");
|
|
4786
4768
|
const errorOutput = result?.stderr || result?.stdout || "";
|
|
4787
|
-
console.log(
|
|
4788
|
-
console.log(
|
|
4769
|
+
console.log(chalk15.red("\nError:\n"));
|
|
4770
|
+
console.log(chalk15.dim(errorOutput));
|
|
4789
4771
|
migrationSql = await extractMigrationSQL(tool, errorOutput);
|
|
4790
4772
|
if (migrationSql) {
|
|
4791
4773
|
const copied = await copyToClipboard(migrationSql);
|
|
4792
4774
|
if (copied) {
|
|
4793
|
-
console.log(
|
|
4775
|
+
console.log(chalk15.green(`
|
|
4794
4776
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
4795
4777
|
\u2551 \u{1F4CB} MIGRATION SQL COPIED TO CLIPBOARD! \u2551
|
|
4796
4778
|
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -4810,24 +4792,24 @@ async function pushMigration(tool) {
|
|
|
4810
4792
|
initialValue: true
|
|
4811
4793
|
});
|
|
4812
4794
|
if (showSql && !p15.isCancel(showSql)) {
|
|
4813
|
-
console.log(
|
|
4795
|
+
console.log(chalk15.cyan("\n--- SQL Migration ---\n"));
|
|
4814
4796
|
console.log(migrationSql);
|
|
4815
|
-
console.log(
|
|
4797
|
+
console.log(chalk15.cyan("\n--- End SQL ---\n"));
|
|
4816
4798
|
}
|
|
4817
4799
|
} else {
|
|
4818
|
-
console.log(
|
|
4800
|
+
console.log(chalk15.yellow(`
|
|
4819
4801
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
4820
4802
|
\u2551 \u26A0\uFE0F Could not copy to clipboard \u2551
|
|
4821
4803
|
\u2551 \u2551
|
|
4822
4804
|
\u2551 Here's the SQL to run manually: \u2551
|
|
4823
4805
|
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
4824
4806
|
`));
|
|
4825
|
-
console.log(
|
|
4807
|
+
console.log(chalk15.cyan(migrationSql));
|
|
4826
4808
|
}
|
|
4827
4809
|
const sqlPath = path11.join(process.cwd(), ".codebakers", "failed-migration.sql");
|
|
4828
4810
|
await fs12.ensureDir(path11.dirname(sqlPath));
|
|
4829
4811
|
await fs12.writeFile(sqlPath, migrationSql);
|
|
4830
|
-
console.log(
|
|
4812
|
+
console.log(chalk15.dim(`
|
|
4831
4813
|
Also saved to: ${sqlPath}
|
|
4832
4814
|
`));
|
|
4833
4815
|
} else {
|
|
@@ -4837,7 +4819,7 @@ Also saved to: ${sqlPath}
|
|
|
4837
4819
|
}
|
|
4838
4820
|
spinner16.stop("Migration pushed successfully!");
|
|
4839
4821
|
if (result?.stdout) {
|
|
4840
|
-
console.log(
|
|
4822
|
+
console.log(chalk15.dim(result.stdout));
|
|
4841
4823
|
}
|
|
4842
4824
|
p15.log.success("Database updated!");
|
|
4843
4825
|
} catch (error) {
|
|
@@ -4847,8 +4829,8 @@ Also saved to: ${sqlPath}
|
|
|
4847
4829
|
const migrationSql = await extractMigrationSQL(tool, errorMsg);
|
|
4848
4830
|
if (migrationSql) {
|
|
4849
4831
|
await copyToClipboard(migrationSql);
|
|
4850
|
-
console.log(
|
|
4851
|
-
console.log(
|
|
4832
|
+
console.log(chalk15.green("\n\u{1F4CB} Migration SQL copied to clipboard!\n"));
|
|
4833
|
+
console.log(chalk15.cyan(migrationSql));
|
|
4852
4834
|
}
|
|
4853
4835
|
}
|
|
4854
4836
|
}
|
|
@@ -4870,7 +4852,7 @@ async function pullSchema(tool) {
|
|
|
4870
4852
|
}
|
|
4871
4853
|
spinner16.stop("Schema pulled");
|
|
4872
4854
|
if (result?.stdout) {
|
|
4873
|
-
console.log(
|
|
4855
|
+
console.log(chalk15.dim(result.stdout));
|
|
4874
4856
|
}
|
|
4875
4857
|
} catch (error) {
|
|
4876
4858
|
spinner16.stop("Error pulling schema");
|
|
@@ -4961,7 +4943,7 @@ async function copyToClipboard(text17) {
|
|
|
4961
4943
|
|
|
4962
4944
|
// src/commands/prd-maker.ts
|
|
4963
4945
|
import * as p16 from "@clack/prompts";
|
|
4964
|
-
import
|
|
4946
|
+
import chalk16 from "chalk";
|
|
4965
4947
|
import * as fs13 from "fs-extra";
|
|
4966
4948
|
import * as path12 from "path";
|
|
4967
4949
|
import Anthropic3 from "@anthropic-ai/sdk";
|
|
@@ -4976,7 +4958,7 @@ async function prdMakerCommand() {
|
|
|
4976
4958
|
p16.log.error("Anthropic API key not configured.");
|
|
4977
4959
|
return;
|
|
4978
4960
|
}
|
|
4979
|
-
console.log(
|
|
4961
|
+
console.log(chalk16.cyan(`
|
|
4980
4962
|
\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E
|
|
4981
4963
|
\u2502 \u2502
|
|
4982
4964
|
\u2502 \u{1F4DD} CODEBAKERS PRD MAKER \u2502
|
|
@@ -5020,7 +5002,7 @@ async function prdMakerCommand() {
|
|
|
5020
5002
|
await fs13.writeFile(filepath, prd);
|
|
5021
5003
|
const jsonPath = filepath.replace(".md", ".json");
|
|
5022
5004
|
await fs13.writeJson(jsonPath, input, { spaces: 2 });
|
|
5023
|
-
console.log(
|
|
5005
|
+
console.log(chalk16.green(`
|
|
5024
5006
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
5025
5007
|
\u2551 \u2713 PRD Generated Successfully! \u2551
|
|
5026
5008
|
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -5042,9 +5024,9 @@ async function prdMakerCommand() {
|
|
|
5042
5024
|
initialValue: true
|
|
5043
5025
|
});
|
|
5044
5026
|
if (preview && !p16.isCancel(preview)) {
|
|
5045
|
-
console.log(
|
|
5027
|
+
console.log(chalk16.cyan("\n" + "\u2550".repeat(60) + "\n"));
|
|
5046
5028
|
console.log(prd);
|
|
5047
|
-
console.log(
|
|
5029
|
+
console.log(chalk16.cyan("\n" + "\u2550".repeat(60) + "\n"));
|
|
5048
5030
|
}
|
|
5049
5031
|
const nextStep = await p16.select({
|
|
5050
5032
|
message: "What would you like to do next?",
|
|
@@ -5090,7 +5072,7 @@ async function conductPRDInterview(inputMethod) {
|
|
|
5090
5072
|
if (p16.isCancel(response)) return null;
|
|
5091
5073
|
return response;
|
|
5092
5074
|
};
|
|
5093
|
-
console.log(
|
|
5075
|
+
console.log(chalk16.bold("\n\u{1F4CB} Let's build your PRD!\n"));
|
|
5094
5076
|
const projectName = await getInput(
|
|
5095
5077
|
"What's your project/product name?",
|
|
5096
5078
|
"My Awesome App"
|
|
@@ -5106,8 +5088,8 @@ async function conductPRDInterview(inputMethod) {
|
|
|
5106
5088
|
"Marketing managers at companies with 10-50 employees..."
|
|
5107
5089
|
);
|
|
5108
5090
|
if (!targetUsers) return null;
|
|
5109
|
-
console.log(
|
|
5110
|
-
console.log(
|
|
5091
|
+
console.log(chalk16.bold("\n\u{1F3AF} Core Features\n"));
|
|
5092
|
+
console.log(chalk16.dim('List the main features. Type each one and press Enter. Type "done" when finished.\n'));
|
|
5111
5093
|
const coreFeatures = [];
|
|
5112
5094
|
while (true) {
|
|
5113
5095
|
const feature = await getInput(
|
|
@@ -5118,8 +5100,8 @@ async function conductPRDInterview(inputMethod) {
|
|
|
5118
5100
|
if (feature.toLowerCase() === "done") break;
|
|
5119
5101
|
coreFeatures.push(feature);
|
|
5120
5102
|
}
|
|
5121
|
-
console.log(
|
|
5122
|
-
console.log(
|
|
5103
|
+
console.log(chalk16.bold("\n\u{1F464} User Stories\n"));
|
|
5104
|
+
console.log(chalk16.dim('Describe key user journeys. Type "done" when finished.\n'));
|
|
5123
5105
|
const userStories = [];
|
|
5124
5106
|
while (true) {
|
|
5125
5107
|
const story = await getInput(
|
|
@@ -5211,9 +5193,9 @@ async function checkVoiceAvailability2() {
|
|
|
5211
5193
|
return false;
|
|
5212
5194
|
}
|
|
5213
5195
|
async function getVoiceInput2(prompt) {
|
|
5214
|
-
console.log(
|
|
5196
|
+
console.log(chalk16.cyan(`
|
|
5215
5197
|
\u{1F3A4} ${prompt}`));
|
|
5216
|
-
console.log(
|
|
5198
|
+
console.log(chalk16.dim(" Press Enter to start recording, then speak. Press Enter again to stop.\n"));
|
|
5217
5199
|
const ready = await p16.confirm({
|
|
5218
5200
|
message: "Ready to record?",
|
|
5219
5201
|
initialValue: true
|
|
@@ -5235,7 +5217,7 @@ async function getVoiceInput2(prompt) {
|
|
|
5235
5217
|
}
|
|
5236
5218
|
spinner16.stop("Recording complete");
|
|
5237
5219
|
if (transcription) {
|
|
5238
|
-
console.log(
|
|
5220
|
+
console.log(chalk16.green(`
|
|
5239
5221
|
Heard: "${transcription}"
|
|
5240
5222
|
`));
|
|
5241
5223
|
const confirm13 = await p16.confirm({
|
|
@@ -5263,7 +5245,7 @@ async function getVoiceInput2(prompt) {
|
|
|
5263
5245
|
}
|
|
5264
5246
|
} catch (error) {
|
|
5265
5247
|
spinner16.stop("Recording failed");
|
|
5266
|
-
console.log(
|
|
5248
|
+
console.log(chalk16.yellow("Voice input failed. Falling back to text."));
|
|
5267
5249
|
}
|
|
5268
5250
|
const text17 = await p16.text({ message: prompt });
|
|
5269
5251
|
return p16.isCancel(text17) ? null : text17;
|
|
@@ -5291,7 +5273,7 @@ if ($result) { Write-Output $result.Text }
|
|
|
5291
5273
|
async function recordWithMacOS2() {
|
|
5292
5274
|
const tempFile = `/tmp/codebakers-voice-${Date.now()}.wav`;
|
|
5293
5275
|
try {
|
|
5294
|
-
console.log(
|
|
5276
|
+
console.log(chalk16.dim(" Recording for up to 10 seconds..."));
|
|
5295
5277
|
await execa("sox", [
|
|
5296
5278
|
"-d",
|
|
5297
5279
|
// default input device
|
|
@@ -5465,7 +5447,7 @@ Make it professional, detailed, and actionable. This should be ready to hand off
|
|
|
5465
5447
|
|
|
5466
5448
|
// src/commands/build.ts
|
|
5467
5449
|
import * as p17 from "@clack/prompts";
|
|
5468
|
-
import
|
|
5450
|
+
import chalk17 from "chalk";
|
|
5469
5451
|
import * as fs14 from "fs-extra";
|
|
5470
5452
|
import * as path13 from "path";
|
|
5471
5453
|
import Anthropic4 from "@anthropic-ai/sdk";
|
|
@@ -5474,33 +5456,33 @@ var displayPaused = false;
|
|
|
5474
5456
|
async function buildCommand(prdPath, options = {}) {
|
|
5475
5457
|
const config = new Config();
|
|
5476
5458
|
if (!config.isConfigured()) {
|
|
5477
|
-
console.log(
|
|
5459
|
+
console.log(chalk17.yellow(`
|
|
5478
5460
|
\u26A0\uFE0F CodeBakers isn't set up yet.
|
|
5479
5461
|
|
|
5480
5462
|
Run this first:
|
|
5481
|
-
${
|
|
5463
|
+
${chalk17.cyan("codebakers setup")}
|
|
5482
5464
|
`));
|
|
5483
5465
|
return;
|
|
5484
5466
|
}
|
|
5485
5467
|
const anthropicCreds = config.getCredentials("anthropic");
|
|
5486
5468
|
if (!anthropicCreds?.apiKey) {
|
|
5487
|
-
console.log(
|
|
5469
|
+
console.log(chalk17.yellow(`
|
|
5488
5470
|
\u26A0\uFE0F Anthropic API key not configured.
|
|
5489
5471
|
|
|
5490
5472
|
The parallel build needs Claude AI to work.
|
|
5491
5473
|
|
|
5492
5474
|
Run this to add your API key:
|
|
5493
|
-
${
|
|
5475
|
+
${chalk17.cyan("codebakers setup")}
|
|
5494
5476
|
`));
|
|
5495
5477
|
return;
|
|
5496
5478
|
}
|
|
5497
5479
|
let prdFile = prdPath;
|
|
5498
5480
|
if (!prdFile) {
|
|
5499
|
-
console.log(
|
|
5481
|
+
console.log(chalk17.dim(`
|
|
5500
5482
|
A PRD (Product Requirements Document) describes what you want to build.
|
|
5501
5483
|
|
|
5502
5484
|
Don't have one? Create one with:
|
|
5503
|
-
${
|
|
5485
|
+
${chalk17.cyan("codebakers prd-maker")}
|
|
5504
5486
|
`));
|
|
5505
5487
|
const file = await p17.text({
|
|
5506
5488
|
message: "Path to PRD file:",
|
|
@@ -5511,16 +5493,16 @@ async function buildCommand(prdPath, options = {}) {
|
|
|
5511
5493
|
prdFile = file;
|
|
5512
5494
|
}
|
|
5513
5495
|
if (!await fs14.pathExists(prdFile)) {
|
|
5514
|
-
console.log(
|
|
5496
|
+
console.log(chalk17.red(`
|
|
5515
5497
|
\u274C PRD file not found: ${prdFile}
|
|
5516
5498
|
|
|
5517
5499
|
Make sure the file exists, or create one:
|
|
5518
|
-
${
|
|
5500
|
+
${chalk17.cyan("codebakers prd-maker")}
|
|
5519
5501
|
`));
|
|
5520
5502
|
return;
|
|
5521
5503
|
}
|
|
5522
5504
|
const prdContent = await fs14.readFile(prdFile, "utf-8");
|
|
5523
|
-
console.log(
|
|
5505
|
+
console.log(chalk17.cyan(`
|
|
5524
5506
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
5525
5507
|
\u2551 \u{1F680} CODEBAKERS PARALLEL BUILD \u2551
|
|
5526
5508
|
\u2551 \u2551
|
|
@@ -5541,7 +5523,7 @@ async function buildCommand(prdPath, options = {}) {
|
|
|
5541
5523
|
const totalAgents = buildPlan.waves.reduce((sum, w) => sum + w.agents.length, 0);
|
|
5542
5524
|
const useParallel = !options.sequential && totalAgents > 2;
|
|
5543
5525
|
if (!useParallel) {
|
|
5544
|
-
console.log(
|
|
5526
|
+
console.log(chalk17.dim("\nUsing sequential build (parallel not needed for small projects)\n"));
|
|
5545
5527
|
}
|
|
5546
5528
|
const proceed = await p17.confirm({
|
|
5547
5529
|
message: `Start ${useParallel ? "parallel" : "sequential"} build?`,
|
|
@@ -5579,7 +5561,7 @@ async function buildCommand(prdPath, options = {}) {
|
|
|
5579
5561
|
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5580
5562
|
const minutes = Math.floor(elapsed / 60);
|
|
5581
5563
|
const seconds = elapsed % 60;
|
|
5582
|
-
console.log(
|
|
5564
|
+
console.log(chalk17.green(`
|
|
5583
5565
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
5584
5566
|
\u2551 \u2705 BUILD COMPLETE \u2551
|
|
5585
5567
|
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -5665,24 +5647,24 @@ Think about:
|
|
|
5665
5647
|
return plan;
|
|
5666
5648
|
}
|
|
5667
5649
|
function displayBuildPlan(plan) {
|
|
5668
|
-
console.log(
|
|
5650
|
+
console.log(chalk17.bold(`
|
|
5669
5651
|
\u{1F4CB} Build Plan: ${plan.projectName}
|
|
5670
5652
|
`));
|
|
5671
|
-
console.log(
|
|
5653
|
+
console.log(chalk17.dim(` ${plan.description}
|
|
5672
5654
|
`));
|
|
5673
5655
|
for (const wave of plan.waves) {
|
|
5674
5656
|
const parallel = wave.parallel && wave.agents.length > 1;
|
|
5675
|
-
const mode = parallel ?
|
|
5676
|
-
console.log(
|
|
5657
|
+
const mode = parallel ? chalk17.green("parallel") : chalk17.yellow("sequential");
|
|
5658
|
+
console.log(chalk17.bold(` Wave ${wave.wave} (${mode}):`));
|
|
5677
5659
|
for (const agent of wave.agents) {
|
|
5678
|
-
const deps = agent.dependencies.length > 0 ?
|
|
5660
|
+
const deps = agent.dependencies.length > 0 ? chalk17.dim(` \u2190 needs: ${agent.dependencies.join(", ")}`) : "";
|
|
5679
5661
|
console.log(` \u2022 ${agent.name} ${deps}`);
|
|
5680
5662
|
}
|
|
5681
5663
|
console.log("");
|
|
5682
5664
|
}
|
|
5683
5665
|
const totalAgents = plan.waves.reduce((sum, w) => sum + w.agents.length, 0);
|
|
5684
5666
|
const parallelWaves = plan.waves.filter((w) => w.parallel && w.agents.length > 1).length;
|
|
5685
|
-
console.log(
|
|
5667
|
+
console.log(chalk17.dim(` Total: ${totalAgents} features, ${plan.waves.length} waves, ${parallelWaves} parallel
|
|
5686
5668
|
`));
|
|
5687
5669
|
}
|
|
5688
5670
|
async function runSetupPhase(anthropic, plan, projectPath) {
|
|
@@ -5735,14 +5717,14 @@ Use TypeScript. Include all necessary imports.`
|
|
|
5735
5717
|
}
|
|
5736
5718
|
async function executeParallelBuild(anthropic, plan, projectPath, config) {
|
|
5737
5719
|
for (const wave of plan.waves) {
|
|
5738
|
-
console.log(
|
|
5720
|
+
console.log(chalk17.bold(`
|
|
5739
5721
|
\u{1F3D7}\uFE0F Wave ${wave.wave} of ${plan.waves.length}`));
|
|
5740
5722
|
if (wave.parallel && wave.agents.length > 1) {
|
|
5741
|
-
console.log(
|
|
5723
|
+
console.log(chalk17.dim(` Running ${wave.agents.length} agents in parallel
|
|
5742
5724
|
`));
|
|
5743
5725
|
await executeWaveParallel(anthropic, wave.agents, projectPath, plan);
|
|
5744
5726
|
} else {
|
|
5745
|
-
console.log(
|
|
5727
|
+
console.log(chalk17.dim(` Running sequentially
|
|
5746
5728
|
`));
|
|
5747
5729
|
for (const agent of wave.agents) {
|
|
5748
5730
|
await executeAgent(anthropic, agent, projectPath, plan);
|
|
@@ -5943,11 +5925,11 @@ async function askUserQuestion(agent, question, onProgress) {
|
|
|
5943
5925
|
agent.status = "asking";
|
|
5944
5926
|
if (onProgress) onProgress(agent.progress, "Waiting for your input...");
|
|
5945
5927
|
console.log("\n");
|
|
5946
|
-
console.log(
|
|
5947
|
-
console.log(
|
|
5948
|
-
console.log(
|
|
5928
|
+
console.log(chalk17.cyan(` \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`));
|
|
5929
|
+
console.log(chalk17.cyan(` \u2502 \u{1F916} ${agent.name} needs your input`));
|
|
5930
|
+
console.log(chalk17.cyan(` \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`));
|
|
5949
5931
|
if (question.context) {
|
|
5950
|
-
console.log(
|
|
5932
|
+
console.log(chalk17.dim(` ${question.context}
|
|
5951
5933
|
`));
|
|
5952
5934
|
}
|
|
5953
5935
|
const answer = await p17.select({
|
|
@@ -5955,12 +5937,12 @@ async function askUserQuestion(agent, question, onProgress) {
|
|
|
5955
5937
|
options: question.options.map((o) => ({ value: o, label: o }))
|
|
5956
5938
|
});
|
|
5957
5939
|
if (p17.isCancel(answer)) {
|
|
5958
|
-
console.log(
|
|
5940
|
+
console.log(chalk17.yellow(` Using default: ${question.options[0]}`));
|
|
5959
5941
|
agent.status = previousStatus;
|
|
5960
5942
|
displayPaused = false;
|
|
5961
5943
|
return question.options[0];
|
|
5962
5944
|
}
|
|
5963
|
-
console.log(
|
|
5945
|
+
console.log(chalk17.green(` \u2713 Got it: ${answer}
|
|
5964
5946
|
`));
|
|
5965
5947
|
agent.status = previousStatus;
|
|
5966
5948
|
displayPaused = false;
|
|
@@ -6059,7 +6041,7 @@ async function mergeWaveBranches(agents, projectPath) {
|
|
|
6059
6041
|
await execa9("git", ["merge", agent.branch, "--no-edit"], { cwd: projectPath });
|
|
6060
6042
|
await execa9("git", ["branch", "-d", agent.branch], { cwd: projectPath, reject: false });
|
|
6061
6043
|
} catch (error) {
|
|
6062
|
-
console.log(
|
|
6044
|
+
console.log(chalk17.yellow(` Warning: Merge issue with ${agent.name}, continuing...`));
|
|
6063
6045
|
await execa9("git", ["merge", "--abort"], { cwd: projectPath, reject: false });
|
|
6064
6046
|
}
|
|
6065
6047
|
}
|
|
@@ -6108,7 +6090,7 @@ var ProgressDisplay = class {
|
|
|
6108
6090
|
for (const agent of this.agents) {
|
|
6109
6091
|
const icon = this.getStatusIcon(agent.status);
|
|
6110
6092
|
const bar = this.getProgressBar(agent.progress);
|
|
6111
|
-
const action = agent.currentAction ?
|
|
6093
|
+
const action = agent.currentAction ? chalk17.dim(` ${agent.currentAction}`) : "";
|
|
6112
6094
|
console.log(` ${icon} ${agent.name.padEnd(15)} ${bar} ${agent.progress.toString().padStart(3)}%${action}`);
|
|
6113
6095
|
}
|
|
6114
6096
|
console.log("");
|
|
@@ -6117,17 +6099,17 @@ var ProgressDisplay = class {
|
|
|
6117
6099
|
getStatusIcon(status) {
|
|
6118
6100
|
switch (status) {
|
|
6119
6101
|
case "waiting":
|
|
6120
|
-
return
|
|
6102
|
+
return chalk17.gray("\u25CB");
|
|
6121
6103
|
case "running":
|
|
6122
|
-
return
|
|
6104
|
+
return chalk17.blue("\u25CF");
|
|
6123
6105
|
case "healing":
|
|
6124
|
-
return
|
|
6106
|
+
return chalk17.yellow("\u2695");
|
|
6125
6107
|
case "asking":
|
|
6126
|
-
return
|
|
6108
|
+
return chalk17.magenta("?");
|
|
6127
6109
|
case "done":
|
|
6128
|
-
return
|
|
6110
|
+
return chalk17.green("\u2713");
|
|
6129
6111
|
case "error":
|
|
6130
|
-
return
|
|
6112
|
+
return chalk17.red("\u2717");
|
|
6131
6113
|
default:
|
|
6132
6114
|
return "?";
|
|
6133
6115
|
}
|
|
@@ -6136,7 +6118,7 @@ var ProgressDisplay = class {
|
|
|
6136
6118
|
const width = 20;
|
|
6137
6119
|
const filled = Math.round(progress / 100 * width);
|
|
6138
6120
|
const empty = width - filled;
|
|
6139
|
-
return
|
|
6121
|
+
return chalk17.green("\u2588".repeat(filled)) + chalk17.gray("\u2591".repeat(empty));
|
|
6140
6122
|
}
|
|
6141
6123
|
};
|
|
6142
6124
|
async function writeFilesFromResponse(text17, projectPath) {
|
|
@@ -6158,7 +6140,7 @@ function sleep(ms) {
|
|
|
6158
6140
|
|
|
6159
6141
|
// src/commands/integrate.ts
|
|
6160
6142
|
import * as p18 from "@clack/prompts";
|
|
6161
|
-
import
|
|
6143
|
+
import chalk18 from "chalk";
|
|
6162
6144
|
import * as fs15 from "fs-extra";
|
|
6163
6145
|
import * as path14 from "path";
|
|
6164
6146
|
import open2 from "open";
|
|
@@ -6695,7 +6677,7 @@ var INTEGRATIONS = [
|
|
|
6695
6677
|
}
|
|
6696
6678
|
];
|
|
6697
6679
|
async function integrateCommand(integrationId) {
|
|
6698
|
-
console.log(
|
|
6680
|
+
console.log(chalk18.cyan(`
|
|
6699
6681
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
6700
6682
|
\u2551 \u{1F50C} ONE-CLICK INTEGRATIONS \u2551
|
|
6701
6683
|
\u2551 \u2551
|
|
@@ -6706,7 +6688,7 @@ async function integrateCommand(integrationId) {
|
|
|
6706
6688
|
const integration2 = INTEGRATIONS.find((i) => i.id === integrationId);
|
|
6707
6689
|
if (!integration2) {
|
|
6708
6690
|
p18.log.error(`Unknown integration: ${integrationId}`);
|
|
6709
|
-
console.log(
|
|
6691
|
+
console.log(chalk18.dim(`
|
|
6710
6692
|
Available: ${INTEGRATIONS.map((i) => i.id).join(", ")}`));
|
|
6711
6693
|
return;
|
|
6712
6694
|
}
|
|
@@ -6771,7 +6753,7 @@ Available: ${INTEGRATIONS.map((i) => i.id).join(", ")}`));
|
|
|
6771
6753
|
await installIntegration(integration);
|
|
6772
6754
|
}
|
|
6773
6755
|
async function installIntegration(integration) {
|
|
6774
|
-
console.log(
|
|
6756
|
+
console.log(chalk18.cyan(`
|
|
6775
6757
|
\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
|
|
6776
6758
|
\u2502 ${integration.icon} Installing ${integration.name}
|
|
6777
6759
|
\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
|
|
@@ -6784,21 +6766,21 @@ async function installIntegration(integration) {
|
|
|
6784
6766
|
cwd: process.cwd(),
|
|
6785
6767
|
reject: false
|
|
6786
6768
|
});
|
|
6787
|
-
spinner17.stop(
|
|
6769
|
+
spinner17.stop(chalk18.green("\u2713 Packages installed"));
|
|
6788
6770
|
} catch {
|
|
6789
|
-
spinner17.stop(
|
|
6771
|
+
spinner17.stop(chalk18.yellow("\u26A0 Package install had issues (may already be installed)"));
|
|
6790
6772
|
}
|
|
6791
6773
|
}
|
|
6792
6774
|
if (integration.envVars.length > 0) {
|
|
6793
|
-
console.log(
|
|
6775
|
+
console.log(chalk18.cyan(`
|
|
6794
6776
|
\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
|
|
6795
6777
|
\u2502 \u{1F4CB} HOW TO GET YOUR API KEYS
|
|
6796
6778
|
\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
|
|
6797
6779
|
`));
|
|
6798
6780
|
integration.steps.forEach((step, i) => {
|
|
6799
|
-
console.log(
|
|
6781
|
+
console.log(chalk18.white(` ${i + 1}. ${step}`));
|
|
6800
6782
|
});
|
|
6801
|
-
console.log(
|
|
6783
|
+
console.log(chalk18.dim(`
|
|
6802
6784
|
Dashboard: ${integration.dashboardUrl}
|
|
6803
6785
|
Docs: ${integration.docs}
|
|
6804
6786
|
`));
|
|
@@ -6808,19 +6790,19 @@ async function installIntegration(integration) {
|
|
|
6808
6790
|
});
|
|
6809
6791
|
if (openDashboard && !p18.isCancel(openDashboard)) {
|
|
6810
6792
|
await open2(integration.dashboardUrl);
|
|
6811
|
-
console.log(
|
|
6793
|
+
console.log(chalk18.dim(`
|
|
6812
6794
|
\u2713 Browser opened! Get your keys and come back.
|
|
6813
6795
|
`));
|
|
6814
6796
|
await sleep2(2e3);
|
|
6815
6797
|
}
|
|
6816
|
-
console.log(
|
|
6798
|
+
console.log(chalk18.cyan(`
|
|
6817
6799
|
Enter your credentials:
|
|
6818
6800
|
`));
|
|
6819
6801
|
const credentials = {};
|
|
6820
6802
|
for (const envVar of integration.envVars) {
|
|
6821
6803
|
const hint = integration.envVarHints?.[envVar] || "Paste here...";
|
|
6822
6804
|
const isPublic = envVar.startsWith("NEXT_PUBLIC_");
|
|
6823
|
-
const label = isPublic ?
|
|
6805
|
+
const label = isPublic ? chalk18.yellow("(public)") : chalk18.green("(secret)");
|
|
6824
6806
|
const value = await p18.text({
|
|
6825
6807
|
message: `${envVar} ${label}`,
|
|
6826
6808
|
placeholder: hint,
|
|
@@ -6830,15 +6812,15 @@ async function installIntegration(integration) {
|
|
|
6830
6812
|
credentials[envVar] = value;
|
|
6831
6813
|
}
|
|
6832
6814
|
await saveEnvVars(credentials);
|
|
6833
|
-
console.log(
|
|
6815
|
+
console.log(chalk18.green(`
|
|
6834
6816
|
\u2713 Saved to .env.local
|
|
6835
6817
|
`));
|
|
6836
6818
|
}
|
|
6837
6819
|
const spinner16 = p18.spinner();
|
|
6838
6820
|
spinner16.start("Creating setup file...");
|
|
6839
6821
|
await generateSetupCode(integration);
|
|
6840
|
-
spinner16.stop(
|
|
6841
|
-
console.log(
|
|
6822
|
+
spinner16.stop(chalk18.green("\u2713 Setup complete"));
|
|
6823
|
+
console.log(chalk18.green(`
|
|
6842
6824
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
6843
6825
|
\u2551 \u2705 ${integration.name} installed!
|
|
6844
6826
|
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -6946,7 +6928,7 @@ function sleep2(ms) {
|
|
|
6946
6928
|
|
|
6947
6929
|
// src/commands/website.ts
|
|
6948
6930
|
import * as p19 from "@clack/prompts";
|
|
6949
|
-
import
|
|
6931
|
+
import chalk19 from "chalk";
|
|
6950
6932
|
import * as fs16 from "fs-extra";
|
|
6951
6933
|
import * as path15 from "path";
|
|
6952
6934
|
import Anthropic5 from "@anthropic-ai/sdk";
|
|
@@ -7060,30 +7042,30 @@ var TEMPLATES = [
|
|
|
7060
7042
|
async function websiteCommand() {
|
|
7061
7043
|
const config = new Config();
|
|
7062
7044
|
if (!config.isConfigured()) {
|
|
7063
|
-
console.log(
|
|
7045
|
+
console.log(chalk19.yellow(`
|
|
7064
7046
|
\u26A0\uFE0F CodeBakers isn't set up yet.
|
|
7065
7047
|
|
|
7066
7048
|
Run this first:
|
|
7067
|
-
${
|
|
7049
|
+
${chalk19.cyan("codebakers setup")}
|
|
7068
7050
|
`));
|
|
7069
7051
|
return;
|
|
7070
7052
|
}
|
|
7071
7053
|
const anthropicCreds = config.getCredentials("anthropic");
|
|
7072
7054
|
if (!anthropicCreds?.apiKey) {
|
|
7073
|
-
console.log(
|
|
7055
|
+
console.log(chalk19.yellow(`
|
|
7074
7056
|
\u26A0\uFE0F Anthropic API key not configured.
|
|
7075
7057
|
|
|
7076
7058
|
The website builder needs Claude AI to generate code.
|
|
7077
7059
|
|
|
7078
7060
|
Run this to add your API key:
|
|
7079
|
-
${
|
|
7061
|
+
${chalk19.cyan("codebakers setup")}
|
|
7080
7062
|
|
|
7081
7063
|
Get an API key at:
|
|
7082
|
-
${
|
|
7064
|
+
${chalk19.dim("https://console.anthropic.com/settings/keys")}
|
|
7083
7065
|
`));
|
|
7084
7066
|
return;
|
|
7085
7067
|
}
|
|
7086
|
-
console.log(
|
|
7068
|
+
console.log(chalk19.cyan(`
|
|
7087
7069
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
7088
7070
|
\u2551 \u{1F310} WEBSITE BUILDER \u2551
|
|
7089
7071
|
\u2551 \u2551
|
|
@@ -7110,14 +7092,14 @@ async function websiteCommand() {
|
|
|
7110
7092
|
websiteSpec = await cloneDesign(anthropic);
|
|
7111
7093
|
}
|
|
7112
7094
|
if (!websiteSpec) return;
|
|
7113
|
-
console.log(
|
|
7095
|
+
console.log(chalk19.cyan(`
|
|
7114
7096
|
\u{1F4CB} Website Plan:
|
|
7115
7097
|
`));
|
|
7116
|
-
console.log(
|
|
7117
|
-
console.log(
|
|
7098
|
+
console.log(chalk19.bold(` ${websiteSpec.name}`));
|
|
7099
|
+
console.log(chalk19.dim(` ${websiteSpec.description}
|
|
7118
7100
|
`));
|
|
7119
|
-
console.log(
|
|
7120
|
-
console.log(
|
|
7101
|
+
console.log(chalk19.dim(` Style: ${websiteSpec.style}`));
|
|
7102
|
+
console.log(chalk19.dim(` Sections: ${websiteSpec.sections.join(", ")}
|
|
7121
7103
|
`));
|
|
7122
7104
|
const confirm13 = await p19.confirm({
|
|
7123
7105
|
message: "Build this website?",
|
|
@@ -7127,11 +7109,11 @@ async function websiteCommand() {
|
|
|
7127
7109
|
await buildWebsite(anthropic, websiteSpec, config);
|
|
7128
7110
|
}
|
|
7129
7111
|
async function describeWebsite(anthropic) {
|
|
7130
|
-
console.log(
|
|
7131
|
-
console.log(
|
|
7132
|
-
console.log(
|
|
7133
|
-
console.log(
|
|
7134
|
-
console.log(
|
|
7112
|
+
console.log(chalk19.dim("\n Describe your website. Be as detailed as you want.\n"));
|
|
7113
|
+
console.log(chalk19.dim(" Examples:"));
|
|
7114
|
+
console.log(chalk19.dim(' \u2022 "A landing page for my AI writing tool called WriteBot"'));
|
|
7115
|
+
console.log(chalk19.dim(' \u2022 "Portfolio site for a photographer, dark theme, minimal"'));
|
|
7116
|
+
console.log(chalk19.dim(' \u2022 "Coffee shop website with menu, location, and online ordering"\n'));
|
|
7135
7117
|
const description = await textWithVoice({
|
|
7136
7118
|
message: "Describe your website:",
|
|
7137
7119
|
placeholder: "A landing page for..."
|
|
@@ -7262,11 +7244,11 @@ Make the content specific and compelling for this business.`
|
|
|
7262
7244
|
return JSON.parse(jsonMatch[0]);
|
|
7263
7245
|
}
|
|
7264
7246
|
async function cloneDesign(anthropic) {
|
|
7265
|
-
console.log(
|
|
7266
|
-
console.log(
|
|
7267
|
-
console.log(
|
|
7268
|
-
console.log(
|
|
7269
|
-
console.log(
|
|
7247
|
+
console.log(chalk19.dim("\n Describe a website design you like.\n"));
|
|
7248
|
+
console.log(chalk19.dim(" Examples:"));
|
|
7249
|
+
console.log(chalk19.dim(' \u2022 "Like Linear.app - minimal, clean, dark mode"'));
|
|
7250
|
+
console.log(chalk19.dim(' \u2022 "Like Stripe - professional, lots of gradients"'));
|
|
7251
|
+
console.log(chalk19.dim(' \u2022 "Like Notion - simple, friendly, illustrated"\n'));
|
|
7270
7252
|
const inspiration = await textWithVoice({
|
|
7271
7253
|
message: "What site do you want to be inspired by?",
|
|
7272
7254
|
placeholder: "Like Linear.app but for..."
|
|
@@ -7332,7 +7314,7 @@ async function buildWebsite(anthropic, spec, config) {
|
|
|
7332
7314
|
if (!overwrite || p19.isCancel(overwrite)) return;
|
|
7333
7315
|
await fs16.remove(projectPath);
|
|
7334
7316
|
}
|
|
7335
|
-
console.log(
|
|
7317
|
+
console.log(chalk19.cyan(`
|
|
7336
7318
|
\u{1F3D7}\uFE0F Building ${spec.name}...
|
|
7337
7319
|
`));
|
|
7338
7320
|
const spinner16 = p19.spinner();
|
|
@@ -7431,7 +7413,7 @@ Make it production-quality and visually impressive.`
|
|
|
7431
7413
|
await execa11("git", ["add", "."], { cwd: projectPath, reject: false });
|
|
7432
7414
|
await execa11("git", ["commit", "-m", "Initial website build by CodeBakers"], { cwd: projectPath, reject: false });
|
|
7433
7415
|
spinner16.stop("Git initialized");
|
|
7434
|
-
console.log(
|
|
7416
|
+
console.log(chalk19.green(`
|
|
7435
7417
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
7436
7418
|
\u2551 \u2705 Website built successfully! \u2551
|
|
7437
7419
|
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -7455,7 +7437,7 @@ Make it production-quality and visually impressive.`
|
|
|
7455
7437
|
initialValue: true
|
|
7456
7438
|
});
|
|
7457
7439
|
if (openDev && !p19.isCancel(openDev)) {
|
|
7458
|
-
console.log(
|
|
7440
|
+
console.log(chalk19.dim("\n Starting dev server...\n"));
|
|
7459
7441
|
process.chdir(projectPath);
|
|
7460
7442
|
await execa11("npm", ["run", "dev"], {
|
|
7461
7443
|
stdio: "inherit",
|
|
@@ -7632,7 +7614,7 @@ If unclear between multiple commands, use the most likely one with lower confide
|
|
|
7632
7614
|
}
|
|
7633
7615
|
|
|
7634
7616
|
// src/index.ts
|
|
7635
|
-
var
|
|
7617
|
+
var VERSION = "2.3.8";
|
|
7636
7618
|
var logo = `
|
|
7637
7619
|
\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
7620
|
\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
|
|
@@ -7644,12 +7626,12 @@ var logo = `
|
|
|
7644
7626
|
async function showMainMenu() {
|
|
7645
7627
|
const config = new Config();
|
|
7646
7628
|
console.log(gradient.pastel.multiline(logo));
|
|
7647
|
-
console.log(
|
|
7629
|
+
console.log(chalk20.dim(` v${VERSION} \u2014 AI dev team that follows the rules
|
|
7648
7630
|
`));
|
|
7649
7631
|
const hasAnthropic = !!config.getCredentials("anthropic")?.apiKey;
|
|
7650
7632
|
if (!hasAnthropic) {
|
|
7651
7633
|
console.log(boxen2(
|
|
7652
|
-
|
|
7634
|
+
chalk20.yellow("Welcome to CodeBakers!\n\n") + chalk20.white("Let's connect your Anthropic API key so the AI can work.\n") + chalk20.dim("(Takes about 1 minute)"),
|
|
7653
7635
|
{ padding: 1, borderColor: "yellow", borderStyle: "round" }
|
|
7654
7636
|
));
|
|
7655
7637
|
await setupCommand();
|
|
@@ -7662,31 +7644,31 @@ async function showMainMenu() {
|
|
|
7662
7644
|
const folderName = path16.basename(cwd);
|
|
7663
7645
|
if (inProject && projectConfig) {
|
|
7664
7646
|
const framework = projectConfig.framework || "detected";
|
|
7665
|
-
console.log(
|
|
7666
|
-
console.log(
|
|
7647
|
+
console.log(chalk20.cyan(` \u{1F4C1} Working in: ${chalk20.bold(folderName)}`));
|
|
7648
|
+
console.log(chalk20.dim(` ${framework} project
|
|
7667
7649
|
`));
|
|
7668
7650
|
await showProjectMenu(config);
|
|
7669
7651
|
} else {
|
|
7670
|
-
console.log(
|
|
7671
|
-
console.log(
|
|
7652
|
+
console.log(chalk20.cyan(` \u{1F4C1} Current folder: ${chalk20.bold(cwd)}`));
|
|
7653
|
+
console.log(chalk20.dim(` Not a project folder
|
|
7672
7654
|
`));
|
|
7673
7655
|
await showStartMenu(config);
|
|
7674
7656
|
}
|
|
7675
7657
|
}
|
|
7676
7658
|
async function showStartMenu(config) {
|
|
7677
|
-
console.log(
|
|
7659
|
+
console.log(chalk20.cyan("\n \u2139\uFE0F This folder doesn't have a project yet.\n"));
|
|
7678
7660
|
let keepRunning = true;
|
|
7679
7661
|
while (keepRunning) {
|
|
7680
|
-
console.log(
|
|
7681
|
-
console.log(
|
|
7682
|
-
console.log(
|
|
7683
|
-
console.log(
|
|
7684
|
-
console.log(
|
|
7685
|
-
console.log(
|
|
7686
|
-
console.log(
|
|
7687
|
-
console.log(
|
|
7688
|
-
console.log(
|
|
7689
|
-
console.log(
|
|
7662
|
+
console.log(chalk20.white(" What would you like to do?\n"));
|
|
7663
|
+
console.log(chalk20.green(" 1.") + " \u{1F310} Build a website " + chalk20.dim("- Describe it, AI builds it"));
|
|
7664
|
+
console.log(chalk20.green(" 2.") + " \u{1F195} Create new project " + chalk20.dim("- Start with Next.js, React, etc."));
|
|
7665
|
+
console.log(chalk20.green(" 3.") + " \u270F\uFE0F Plan my project " + chalk20.dim("- Create a detailed plan first"));
|
|
7666
|
+
console.log(chalk20.green(" 4.") + " \u{1F3D7}\uFE0F Build from plan " + chalk20.dim("- I already have a PRD file"));
|
|
7667
|
+
console.log(chalk20.green(" 5.") + " \u{1F31F} Get expert advice " + chalk20.dim("- AI consultants help you decide"));
|
|
7668
|
+
console.log(chalk20.green(" 6.") + " \u{1F50C} Add a service " + chalk20.dim("- Stripe, Supabase, Auth, etc."));
|
|
7669
|
+
console.log(chalk20.green(" 7.") + " \u2699\uFE0F Settings " + chalk20.dim("- API keys & preferences"));
|
|
7670
|
+
console.log(chalk20.green(" 8.") + " \u2753 Help " + chalk20.dim("- Learn how CodeBakers works"));
|
|
7671
|
+
console.log(chalk20.green(" 0.") + " \u{1F6AA} Return to terminal " + chalk20.dim("- Go back to command line"));
|
|
7690
7672
|
console.log("");
|
|
7691
7673
|
const choice = await p21.text({
|
|
7692
7674
|
message: "Enter a number (0-8):",
|
|
@@ -7738,34 +7720,34 @@ async function showStartMenu(config) {
|
|
|
7738
7720
|
}
|
|
7739
7721
|
function showExitMessage() {
|
|
7740
7722
|
console.log("");
|
|
7741
|
-
console.log(
|
|
7742
|
-
console.log(
|
|
7723
|
+
console.log(chalk20.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"));
|
|
7724
|
+
console.log(chalk20.white(" You're back in the terminal."));
|
|
7743
7725
|
console.log("");
|
|
7744
|
-
console.log(
|
|
7745
|
-
console.log(
|
|
7726
|
+
console.log(chalk20.dim(" To start CodeBakers again, type:"));
|
|
7727
|
+
console.log(chalk20.green(" codebakers"));
|
|
7746
7728
|
console.log("");
|
|
7747
|
-
console.log(
|
|
7748
|
-
console.log(
|
|
7749
|
-
console.log(
|
|
7750
|
-
console.log(
|
|
7751
|
-
console.log(
|
|
7729
|
+
console.log(chalk20.dim(" Quick commands you can run directly:"));
|
|
7730
|
+
console.log(chalk20.dim(" codebakers website") + chalk20.gray(" - Build a website"));
|
|
7731
|
+
console.log(chalk20.dim(" codebakers code") + chalk20.gray(" - Code with AI"));
|
|
7732
|
+
console.log(chalk20.dim(" codebakers help") + chalk20.gray(" - See all commands"));
|
|
7733
|
+
console.log(chalk20.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
7734
|
console.log("");
|
|
7753
7735
|
}
|
|
7754
7736
|
async function showProjectMenu(config) {
|
|
7755
|
-
console.log(
|
|
7737
|
+
console.log(chalk20.cyan("\n \u2139\uFE0F I found an existing project in this folder.\n"));
|
|
7756
7738
|
let keepRunning = true;
|
|
7757
7739
|
while (keepRunning) {
|
|
7758
|
-
console.log(
|
|
7759
|
-
console.log(
|
|
7760
|
-
console.log(
|
|
7761
|
-
console.log(
|
|
7762
|
-
console.log(
|
|
7763
|
-
console.log(
|
|
7764
|
-
console.log(
|
|
7765
|
-
console.log(
|
|
7766
|
-
console.log(
|
|
7767
|
-
console.log(
|
|
7768
|
-
console.log(
|
|
7740
|
+
console.log(chalk20.white(" What would you like to do with this project?\n"));
|
|
7741
|
+
console.log(chalk20.green(" 1.") + " \u{1F4AC} Code with AI " + chalk20.dim("- Tell AI what to build or fix"));
|
|
7742
|
+
console.log(chalk20.green(" 2.") + " \u{1F680} Deploy to production " + chalk20.dim("- Make your site live"));
|
|
7743
|
+
console.log(chalk20.green(" 3.") + " \u{1F50D} Check my code " + chalk20.dim("- Find issues & improvements"));
|
|
7744
|
+
console.log(chalk20.green(" 4.") + " \u{1F527} Fix errors for me " + chalk20.dim("- AI repairs broken code"));
|
|
7745
|
+
console.log(chalk20.green(" 5.") + " \u{1F50C} Add a service " + chalk20.dim("- Stripe, Supabase, Auth, etc."));
|
|
7746
|
+
console.log(chalk20.green(" 6.") + " \u26A1 Create new files " + chalk20.dim("- Components, pages, APIs"));
|
|
7747
|
+
console.log(chalk20.green(" 7.") + " \u{1F195} Start fresh project " + chalk20.dim("- Begin something new"));
|
|
7748
|
+
console.log(chalk20.green(" 8.") + " \u2699\uFE0F Settings " + chalk20.dim("- API keys & preferences"));
|
|
7749
|
+
console.log(chalk20.green(" 9.") + " \u2753 Help " + chalk20.dim("- Learn how CodeBakers works"));
|
|
7750
|
+
console.log(chalk20.green(" 0.") + " \u{1F6AA} Return to terminal " + chalk20.dim("- Go back to command line"));
|
|
7769
7751
|
console.log("");
|
|
7770
7752
|
const choice = await p21.text({
|
|
7771
7753
|
message: "Enter a number (0-9):",
|
|
@@ -7869,56 +7851,56 @@ async function handleAction(action, config) {
|
|
|
7869
7851
|
showHelp2();
|
|
7870
7852
|
break;
|
|
7871
7853
|
default:
|
|
7872
|
-
console.log(
|
|
7854
|
+
console.log(chalk20.yellow("Coming soon!"));
|
|
7873
7855
|
}
|
|
7874
7856
|
}
|
|
7875
7857
|
function showPostSetupInstructions() {
|
|
7876
7858
|
console.log(boxen2(
|
|
7877
|
-
|
|
7859
|
+
chalk20.green.bold("\u2713 Setup complete!\n\n") + chalk20.white("What's next?\n\n") + chalk20.cyan("1. ") + "Navigate to where you want to build:\n" + chalk20.dim(" cd C:\\dev\\my-project\n\n") + chalk20.cyan("2. ") + "Run CodeBakers:\n" + chalk20.dim(" codebakers\n\n") + chalk20.white("Or build a website right now:\n") + chalk20.dim(" codebakers website"),
|
|
7878
7860
|
{ padding: 1, borderColor: "green", borderStyle: "round" }
|
|
7879
7861
|
));
|
|
7880
7862
|
}
|
|
7881
7863
|
function showPostBuildInstructions(projectName, projectPath) {
|
|
7882
7864
|
const displayPath = projectPath || projectName;
|
|
7883
7865
|
console.log(boxen2(
|
|
7884
|
-
|
|
7866
|
+
chalk20.green.bold(`\u2713 ${projectName} created!
|
|
7885
7867
|
|
|
7886
|
-
`) +
|
|
7868
|
+
`) + chalk20.white("Next steps:\n\n") + chalk20.cyan("1. ") + "Go to your project:\n" + chalk20.dim(` cd ${displayPath}
|
|
7887
7869
|
|
|
7888
|
-
`) +
|
|
7870
|
+
`) + chalk20.cyan("2. ") + "Install dependencies:\n" + chalk20.dim(" npm install\n\n") + chalk20.cyan("3. ") + "Start the dev server:\n" + chalk20.dim(" npm run dev\n\n") + chalk20.cyan("4. ") + "Open in browser:\n" + chalk20.dim(" http://localhost:3000\n\n") + chalk20.white("Ready to deploy?\n") + chalk20.dim(" codebakers deploy"),
|
|
7889
7871
|
{ padding: 1, borderColor: "green", borderStyle: "round" }
|
|
7890
7872
|
));
|
|
7891
7873
|
}
|
|
7892
7874
|
function showHelp2() {
|
|
7893
7875
|
console.log(boxen2(`
|
|
7894
|
-
${
|
|
7895
|
-
|
|
7896
|
-
${
|
|
7897
|
-
${
|
|
7898
|
-
${
|
|
7899
|
-
${
|
|
7900
|
-
${
|
|
7901
|
-
|
|
7902
|
-
${
|
|
7903
|
-
${
|
|
7904
|
-
${
|
|
7905
|
-
${
|
|
7906
|
-
${
|
|
7907
|
-
|
|
7908
|
-
${
|
|
7909
|
-
${
|
|
7910
|
-
${
|
|
7911
|
-
${
|
|
7912
|
-
|
|
7913
|
-
${
|
|
7914
|
-
${
|
|
7915
|
-
${
|
|
7916
|
-
|
|
7917
|
-
${
|
|
7876
|
+
${chalk20.bold("CodeBakers CLI v" + VERSION)} \u2014 AI dev team that follows the rules
|
|
7877
|
+
|
|
7878
|
+
${chalk20.bold.cyan("Getting Started:")}
|
|
7879
|
+
${chalk20.cyan("codebakers")} Interactive menu
|
|
7880
|
+
${chalk20.cyan("codebakers setup")} Connect API keys
|
|
7881
|
+
${chalk20.cyan("codebakers website")} Build website by describing it
|
|
7882
|
+
${chalk20.cyan("codebakers init")} Create new project
|
|
7883
|
+
|
|
7884
|
+
${chalk20.bold.cyan("In a Project:")}
|
|
7885
|
+
${chalk20.cyan("codebakers code")} Chat with AI to build features
|
|
7886
|
+
${chalk20.cyan("codebakers deploy")} Deploy to Vercel
|
|
7887
|
+
${chalk20.cyan("codebakers check")} Check code quality
|
|
7888
|
+
${chalk20.cyan("codebakers fix")} Auto-fix errors
|
|
7889
|
+
|
|
7890
|
+
${chalk20.bold.cyan("Planning:")}
|
|
7891
|
+
${chalk20.cyan("codebakers prd-maker")} Create PRD through interview
|
|
7892
|
+
${chalk20.cyan("codebakers build")} Build from PRD (parallel agents)
|
|
7893
|
+
${chalk20.cyan("codebakers advisors")} Consult AI experts
|
|
7894
|
+
|
|
7895
|
+
${chalk20.bold.cyan("Integrations:")}
|
|
7896
|
+
${chalk20.cyan("codebakers integrate")} 50+ one-click integrations
|
|
7897
|
+
${chalk20.cyan("codebakers gateway")} WhatsApp, Telegram, Discord
|
|
7898
|
+
|
|
7899
|
+
${chalk20.bold("Docs:")} ${chalk20.dim("https://codebakers.dev/docs")}
|
|
7918
7900
|
`, { padding: 1, borderColor: "cyan", borderStyle: "round" }));
|
|
7919
7901
|
}
|
|
7920
7902
|
var program = new Command();
|
|
7921
|
-
program.name("codebakers").description("AI dev team that follows the rules").version(
|
|
7903
|
+
program.name("codebakers").description("AI dev team that follows the rules").version(VERSION).action(showMainMenu);
|
|
7922
7904
|
program.command("setup").description("Configure CodeBakers (API keys)").action(setupCommand);
|
|
7923
7905
|
program.command("init").description("Create a new project").option("-n, --name <n>", "Project name").option("-t, --template <t>", "Template").action(initCommand);
|
|
7924
7906
|
program.command("code [prompt]").description("Start AI coding session").option("-w, --watch", "Watch mode").action(codeCommand);
|
|
@@ -7942,7 +7924,7 @@ program.command("website").alias("site").description("Build website by describin
|
|
|
7942
7924
|
program.command("help").description("Show help").action(showHelp2);
|
|
7943
7925
|
async function handleNaturalLanguage(input) {
|
|
7944
7926
|
const config = new Config();
|
|
7945
|
-
console.log(
|
|
7927
|
+
console.log(chalk20.dim("\n Understanding your request...\n"));
|
|
7946
7928
|
const parsed = await parseNaturalLanguage(input, config);
|
|
7947
7929
|
if (!parsed) {
|
|
7948
7930
|
await codeCommand(input);
|